suppressPackageStartupMessages({
library(knitr)
library(tidyverse)
library(Seurat)
library(SeuratData)
library(scater)
library(zellkonverter)
library(SingleCellExperiment)
library(EnsDb.Mmusculus.v79)
library(Signac)
library(ArchR)
})
## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used
plot_dir <- "/omics/groups/OE0533/internal/katharina/scDoRI/gastrulation_data_new/Kathi/plots/"

The dataset consists of multiome data (scATAC-seq & scRNA-seq) from cells at the timepoints E7.5, E7.75, E8.0, E8.5, E8.75. Additionally, there is data from a CRISPR Knockout of the transcription factor T which is important for the development of the mesoderm lineage. Lastly, there is a CRISPR wildtype sample as a control.

rna_gastr_SE <- readRDS("/omics/groups/OE0533/internal/katharina/scDoRI/gastrulation_data_new/processed/rna/SingleCellExperiment.rds")

# convert to seurat object
rna_seurat <- as.Seurat(rna_gastr_SE, counts = "counts", data = "counts")


proj <- loadArchRProject("/omics/groups/OE0533/internal/katharina/scDoRI/gastrulation_data_new/processed/atac/archR/")

metadata <- getCellColData(proj)

metadata %>% as.data.frame() %>%
  group_by(sample) %>%
  summarise(n = n()) %>% knitr::kable()
sample n
E7.5_rep1 8977
E7.5_rep2 13321
E7.75_rep1 5120
E8.0_rep1 7656
E8.0_rep2 6382
E8.5_CRISPR_T_KO 7529
E8.5_CRISPR_T_WT 7691
E8.5_rep1 11319
E8.5_rep2 11447
E8.75_rep1 4076
E8.75_rep2 5619

metadata <- metadata %>% as.data.frame() %>% 
  dplyr::filter(!is.na(celltype.mapped)) %>%
  rownames_to_column("cell") %>%
  dplyr::filter(cell %in% colnames(rna_seurat)) %>%
  column_to_rownames("cell")

rna_seurat <- rna_seurat[, rownames(metadata)]

rna_seurat <- AddMetaData(rna_seurat, metadata)


rm(rna_gastr_SE)
rm(proj)
gc(reset = TRUE)
        used   (Mb) gc trigger    (Mb)  max used   (Mb)

Ncells 11562723 617.6 20094901 1073.2 11562723 617.6 Vcells 843238129 6433.4 2513628696 19177.5 843238129 6433.4

atac_peaks <- readH5AD("/omics/groups/OE0533/internal/katharina/scDoRI/gastrulation_data_new/processed/atac/anndata/PeakMatrix/PeakMatrix_anndata.h5ad")


atac_seurat <- as.Seurat(atac_peaks, counts = "X", data = "X")


rna_seurat <- readRDS("/omics/groups/OE0533/internal/katharina/scDoRI/gastrulation_data_new/Kathi/rna_seurat")


rm(atac_peaks)
#rm(atac_gene_scores)
gc(reset = TRUE)
##              used    (Mb) gc trigger    (Mb)   max used    (Mb)
## Ncells   11801164   630.3   20094901  1073.2   11801164   630.3
## Vcells 5244487235 40012.3 8718516375 66517.1 5244487235 40012.3

scRNA-seq

Qualtiy Control

Empty Droplets


tibble(sample = rna_seurat@meta.data$sample, umi_per_cell = Matrix::colSums(rna_seurat@assays$RNA@counts)) %>% 
  arrange(sample, desc(umi_per_cell)) %>% 
  group_by(sample) %>% 
  mutate(idx = seq_along(sample)) %>% 
  mutate(cum_umi_per_cell = cumsum(umi_per_cell)) %>% 
  ggplot() +
  geom_line(aes(x = idx, y = cum_umi_per_cell)) +
  facet_wrap(~sample, scales = "fixed") +
  scale_y_log10() + scale_x_log10() +
  ylab("cumulative UMI count") +
  xlab("index")

From the plots below it seems that all cells with percentage of mitochondrial genes above 40% were removed. The early time points E7.5rep1/2 have the highest percentage of mitochondrial genes. Especially E7.5 rep2 seems to have a higher percentage of mitochondrial genes. Conversely, the same replicates from E7.5 have a lower number of features and counts. This means that the E7.5 rep2 and to a lesser extent E7.5 rep1 are of lower quality compared to the other samples. E8.75 rep1/rep2 seem to have the highest quality.

#rename metadata

variables <- c("nFeature_RNA", "nCount_RNA", "mitochondrial_percent_RNA", "ribosomal_percent_RNA")
plots <- map(variables, function(n){
  df <- rna_seurat@meta.data %>%
    arrange(sample) 
  plot <- ggplot(df) +
    geom_violin(aes(x = df %>% pull("sample"), y = df %>% pull(n),
                     fill = df %>% pull("sample")), alpha = .9) +
    geom_boxplot(aes(x = df %>% pull("sample"), y = df %>% pull(n),
                     fill = df %>% pull("sample")), alpha = .2) +
    scale_fill_brewer(palette="Set3") +
    xlab("sample") +
    ylab(paste0(n)) +
    labs(title = paste0(n)) +
    guides(fill=guide_legend(title="sample")) +
    theme(
        axis.text.y = element_text(size = 15),
        axis.title.y = element_text(size = 20),
        plot.title = element_text(hjust = 0.5, size = 25),
        axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1, size =15),
          legend.position = "None", 
          panel.grid.major = element_line(colour = "grey"),   # Major grid lines
          #strip.background = element_rect(colour = "black", fill = "white"),
          panel.background = element_rect(fill = "white", colour = "black"))
  print(plot)
  ggsave(paste0(plot_dir, "_", n, "_qc.pdf"))
  print(plot)

})


print(gridExtra::grid.arrange(grobs = plots, ncol = 2))

## TableGrob (2 x 2) "arrange": 4 grobs
##   z     cells    name           grob
## 1 1 (1-1,1-1) arrange gtable[layout]
## 2 2 (1-1,2-2) arrange gtable[layout]
## 3 3 (2-2,1-1) arrange gtable[layout]
## 4 4 (2-2,2-2) arrange gtable[layout]

Celltypes

print(paste0("There are ", length(unique(rna_seurat@meta.data$celltype.mapped)), " celltypes in the dataset"))
## [1] "There are 37 celltypes in the dataset"

Table with number of cells per celltype

rna_seurat@meta.data %>% group_by(celltype.mapped) %>% 
  summarise(n = n()) %>% knitr::kable(caption = "Number of cells for each celltypes")
Number of cells for each celltypes
celltype.mapped n
Allantois 794
Anterior_Primitive_Streak 167
Blood_progenitors_1 288
Blood_progenitors_2 732
Cardiomyocytes 1390
Caudal_epiblast 746
Caudal_Mesoderm 166
Caudal_neurectoderm 24
Def.endoderm | 505| |Endothelium | 881| |Epiblast | 1047| |Erythroid1 | 2010| |Erythroid2 | 1711| |Erythroid3 | 402| |ExEectoderm 4150
ExE_endoderm 7190
ExE_mesoderm 1707
Forebrain_Midbrain_Hindbrain 5522
Gut 2492
Haematoendothelial_progenitors 1181
Intermediate_mesoderm 1141
Mesenchyme 4240
Mixed_mesoderm 251
Nascent_mesoderm 1466
Neural_crest 1241
NMP 2685
Notochord 149
Paraxial_mesoderm 3458
Parietal_endoderm 591
PGC 50
Pharyngeal_mesoderm 2640
Primitive_Streak 565
Rostral_neurectoderm 2092
Somitic_mesoderm 2174
Spinal_cord 2692
Surface_ectoderm 3650
Visceral_endoderm 773

colPalette_celltypes = c('#532C8A',
 '#c19f70',
 '#f9decf',
 '#c9a997',
 '#B51D8D',
 '#3F84AA',
 '#9e6762',
 '#354E23',
 '#F397C0',
 '#ff891c',
 '#635547',
 '#C72228',
 '#f79083',
 '#EF4E22',
 '#989898',
 '#7F6874',
 '#8870ad',
 '#647a4f',
 '#EF5A9D',
 '#FBBE92',
 '#139992',
 '#cc7818',
 '#DFCDE4',
 '#8EC792',
 '#C594BF',
 '#C3C388',
 '#0F4A9C',
 '#FACB12',
 '#8DB5CE',
 '#1A1A1A',
 '#C9EBFB',
 '#DABE99',
 '#65A83E',
 '#005579',
 '#CDE088',
 '#f7f79e',
 '#F6BFCB')


celltypes <- (rna_seurat@meta.data %>% arrange(celltype.mapped) %>%
                group_by(celltype.mapped) %>% 
  summarise(n = n()))$celltype.mapped


celltypes
##  [1] "Allantois"                      "Anterior_Primitive_Streak"     
##  [3] "Blood_progenitors_1"            "Blood_progenitors_2"           
##  [5] "Cardiomyocytes"                 "Caudal_epiblast"               
##  [7] "Caudal_Mesoderm"                "Caudal_neurectoderm"           
##  [9] "Def._endoderm"                  "Endothelium"                   
## [11] "Epiblast"                       "Erythroid1"                    
## [13] "Erythroid2"                     "Erythroid3"                    
## [15] "ExE_ectoderm"                   "ExE_endoderm"                  
## [17] "ExE_mesoderm"                   "Forebrain_Midbrain_Hindbrain"  
## [19] "Gut"                            "Haematoendothelial_progenitors"
## [21] "Intermediate_mesoderm"          "Mesenchyme"                    
## [23] "Mixed_mesoderm"                 "Nascent_mesoderm"              
## [25] "Neural_crest"                   "NMP"                           
## [27] "Notochord"                      "Paraxial_mesoderm"             
## [29] "Parietal_endoderm"              "PGC"                           
## [31] "Pharyngeal_mesoderm"            "Primitive_Streak"              
## [33] "Rostral_neurectoderm"           "Somitic_mesoderm"              
## [35] "Spinal_cord"                    "Surface_ectoderm"              
## [37] "Visceral_endoderm"

col <- setNames(colPalette_celltypes, celltypes)
col["PGC"] <- "#FACB12"
col["Paraxial_mesoderm"] <- "#8DB5CE"
col["Parietal_endoderm"] <- "#1A1A1A" 
col["Neural_crest"] <- "#C3C388"
col["NMP"] <- "#8EC792"
col["Nascent_mesoderm"] <- "#C594BF"


#celltypes <- (rna_seurat@meta.data %>% group_by(celltype.mapped) %>% 
 # summarise(n = n()))$celltype.mapped

#col <- setNames(colPalette_celltypes, celltypes)

rna_seurat@meta.data %>% group_by(celltype.mapped) %>% 
  summarise(n = n()) %>%# knitr::kable(caption = "Number of cells for each celltypes")
  ggplot() + 
  geom_bar(aes (x = celltype.mapped, y = n,
                fill = celltype.mapped), stat = "identity") +
  scale_fill_manual(values = col) +
  labs(title = "Number of cells per celltype", y = "number of cells", x = "celltype") +
  theme(axis.text.x = element_text(angle = 45, hjust=1, size = 15),
        axis.text.y = element_text(size = 15),
        axis.title.x = element_blank(), # change size of axis title
        axis.title.y = element_text(size = 20),
        plot.title = element_text(hjust = 0.5, size = 25),
        legend.position = "None", 
        panel.grid.major = element_line(colour = "grey"),   # Major grid lines
        panel.background = element_rect(fill = "white", colour = "black"),
        aspect.ratio = 0.4)


ggsave(paste0(plot_dir, "celltypes.pdf"))

rna_seurat@meta.data %>% group_by(sample) %>% 
  summarise(n = n()) %>%# knitr::kable(caption = "Number of cells for each celltypes")
  ggplot() + 
  geom_bar(aes (x = sample, y = n,
                fill = sample), stat = "identity") +
  scale_fill_brewer(palette="Set3") +
  labs(title = "Number of cells per sample", y = "number of cells", x = "sample") +
  theme(axis.text.x = element_text(angle = 45, hjust=1, size = 15),
        axis.text.y = element_text(size = 15),
        axis.title.x = element_blank(), # change size of axis title
        axis.title.y = element_text(size = 20),
        plot.title = element_text(hjust = 0.5, size = 25),
      legend.position = "None", 
      panel.grid.major = element_line(colour = "grey"),   # Major grid lines
      panel.background = element_rect(fill = "white", colour = "black"),
      aspect.ratio = 0.4)


ggsave(paste0(plot_dir, "samples.pdf"))

Normalize & Scale

```#{r} gc(reset = TRUE) rna_seurat <- rna_seurat %>% NormalizeData(verbose = FALSE) %>% ScaleData(verbose = FALSE) %>% FindVariableFeatures(verbose = FALSE)

[0:10, 0:10]

```

PCA

I will proceed with 15 PCs.

rna_seurat <- RunPCA(rna_seurat, features = VariableFeatures(rna_seurat),
             verbose = FALSE)

ElbowPlot(rna_seurat)

pca_plots <- comprehenr::to_list(for (i in 1:15)
  DimPlot(rna_seurat, reduction = "pca", dims = i:(i+1)) +
    theme())

#pca_plots
#gridExtra::grid.arrange(unlist(pca_plots), ncol = 3, nrow = 5)

Clustering

Trying a different resolution for the clustering to see if the Mesenchyme will still separate.

#{r} rna_seurat <- FindNeighbors(rna_seurat, verbose = FALSE) rna_seurat <- FindClusters(rna_seurat, verbose = FALSE, resolution = 0.6) rna_seurat <- RunUMAP(rna_seurat, verbose = FALSE, dims = 1:15)

Visualization

There are two possibilities to proceed with celltype annotations:

In the plot below you can see that the Mesenchyme separates into two clusters, as well as the gut and hematoendothelial progenitors, even though the cells belong to the same celltype. Therefore I visualized the Mesenchyme cells and gut cells according to their respective time point and replicate below. It becomes evident that the Mesenchyme separate into E7.5 and E8.0, E8.5, E8.75. Therefore, the separation is probably a batch effect corresponding to different signatures at different time points. This could also be due to biological differences, however, we should keep in mind that E7.5 was also the time point with lowest quality of cells.

There is one cluster which contains a very heterogeneous population of cells, namely mixed & nascent mesoderm, caudal & rostral neuroectoderm, primitive streak, caudal epiblast and epiblast. As we will see later on, these are primarily early celltypes found at E7.5, which are not present at later timepoints anymore.

# add umap coordinates to metadata for plotting
metadata <- rna_seurat@meta.data
metadata <- metadata %>% mutate(umap1 = rna_seurat[["umap"]]@cell.embeddings[, 1], 
                    umap2 = rna_seurat[["umap"]]@cell.embeddings[, 2])

metadata %>% 
ggplot() +
geom_point(aes(x = umap1, y = umap2, 
               col = celltype.mapped),  size = .6) +
  guides(col=guide_legend(title="Celltype", override.aes = list(size = 5))) +
  scale_color_manual(values = col)+
  xlab("UMAP1") +
  ylab("UMAP2") +
  theme(axis.title.x = element_text(size = 15), # change size of axis title
        axis.title.y = element_text(size = 15), # change size of axis title
        legend.title = element_text(size=15), # change siez of legend title
        legend.text = element_text(size=12), # change size of legend text
        panel.background = element_rect(fill = "white", colour = "black"), # make background white
        legend.key = element_rect(fill = NA), # remove background fill in legend
        aspect.ratio = 1) # make plot quadratic



ggsave(paste0(plot_dir, "celltype_pca.pdf"))
metadata %>% 
ggplot() +
geom_point(aes(x = umap1, y = umap2, 
               col = sample),  size = .4) +
  guides(col=guide_legend(title="Sample", override.aes = list(size = 5))) +
  #scale_color_brewer(palette="Set3") +
  xlab("UMAP1") +
  ylab("UMAP2") +
  theme(axis.title.x = element_text(size = 15),
        axis.title.y = element_text(size = 15),
        legend.title = element_text(size=15),
        panel.background = element_rect(fill = "white", colour = "black"),
        legend.text = element_text(size=12),
        legend.key = element_rect(fill = NA),
        aspect.ratio = 1)


ggsave(paste0(plot_dir, "sample_pca.pdf"))
metadata %>% 
ggplot() +
geom_point(aes(x = umap1, y = umap2, 
               col = ribosomal_percent_RNA),  size = .4) +
  guides(col=guide_legend(title="% Ribosomal genes", 
                          override.aes = list(size = 5))) +
  scale_color_viridis_c() +
  xlab("UMAP1") +
  ylab("UMAP2") +
  theme(axis.title.x = element_text(size = 15),
        axis.title.y = element_text(size = 15),
        legend.title = element_text(size=15),
        panel.background = element_rect(fill = "white", colour = "black"),
        legend.text = element_text(size=12),
        legend.key = element_rect(fill = NA),
        aspect.ratio = 1)


ggsave(paste0(plot_dir, "ribosomal_pca.pdf"))
metadata %>% 
ggplot() +
geom_point(aes(x = umap1, y = umap2, 
               col = mitochondrial_percent_RNA),  size = .4) +
  guides(col=guide_legend(title="% Mitochondrial genes", 
                          override.aes = list(size = 5))) +
  scale_color_viridis_c() +
  xlab("UMAP1") +
  ylab("UMAP2") +
  theme(axis.title.x = element_text(size = 15),
        axis.title.y = element_text(size = 15),
        legend.title = element_text(size=15),
        panel.background = element_rect(fill = "white", colour = "black"),
        legend.text = element_text(size=12),
        legend.key = element_rect(fill = NA),
        aspect.ratio = 1)


ggsave(paste0(plot_dir, "mitochondrial_pca.pdf"))
metadata %>% 
ggplot() +
geom_point(aes(x = umap1, y = umap2, 
               col = nCount_RNA),  size = .4) +
  guides(col=guide_legend(title="#Counts", override.aes = list(size = 5))) +
  scale_color_viridis_c() +
  xlab("UMAP1") +
  ylab("UMAP2") +
  theme(axis.title.x = element_text(size = 15),
        axis.title.y = element_text(size = 15),
        legend.title = element_text(size=15),
        panel.background = element_rect(fill = "white", colour = "black"),
        legend.text = element_text(size=12),
        legend.key = element_rect(fill = NA),
        aspect.ratio = 1)


ggsave(paste0(plot_dir, "counts_pca.pdf"))
metadata %>% 
ggplot() +
geom_point(aes(x = umap1, y = umap2, 
               col = nFeature_RNA),  size = .4) +
  guides(col=guide_legend(title="#Features", 
                          override.aes = list(size = 5))) +
  scale_color_viridis_c() +
  xlab("UMAP1") +
  ylab("UMAP2") +
  theme(axis.title.x = element_text(size = 15),
        axis.title.y = element_text(size = 15),
        legend.title = element_text(size=15),
        panel.background = element_rect(fill = "white", colour = "black"),
        legend.text = element_text(size=12),
        legend.key = element_rect(fill = NA),
        aspect.ratio = 1)


ggsave(paste0(plot_dir, "features_pca.pdf"))
DimPlot(rna_seurat, reduction = "umap", pt.size = 1, 
        group.by = "celltype.mapped", cols = col) #, label = TRUE, repel = TRUE) +

p1 <- DimPlot(subset(rna_seurat, celltype.mapped == "Mesenchyme"), 
        group.by = "sample") + labs(title = "Mesenchyme")
p2 <- DimPlot(subset(rna_seurat, celltype.mapped == c("Gut", "Visceral_endoderm", "Def._endoderm")), 
        group.by = "sample") + labs(title = "Gut, Visceral endoderm, Definitive endoderm")
## Warning in celltype.mapped == c("Gut", "Visceral_endoderm", "Def._endoderm"):
## longer object length is not a multiple of shorter object length

p3 <- p1 <- DimPlot(subset(rna_seurat, celltype.mapped == "Mesenchyme"), 
        group.by = "celltype.mapped") + labs(title = "Mesenchyme")

p4 <-  DimPlot(subset(rna_seurat, celltype.mapped == c("Gut", "Visceral_endoderm", "Def._endoderm")), 
        group.by = "celltype.mapped") + labs(title = "Gut, Visceral endoderm, Definitive endoderm")
## Warning in celltype.mapped == c("Gut", "Visceral_endoderm", "Def._endoderm"):
## longer object length is not a multiple of shorter object length
cowplot::plot_grid(p1, p2, p3, p4, ncol = 2)


ggsave(paste0(plot_dir, "mesenchyme.pdf"))

p1 <- DimPlot(subset(rna_seurat, celltype.mapped == "Mesenchyme"), 
        split.by  = "sample")

p2 <- DimPlot(subset(rna_seurat, celltype.mapped == c("Gut", "Visceral_endoderm", "Def._endoderm")), 
        split.by  = "sample")
## Warning in celltype.mapped == c("Gut", "Visceral_endoderm", "Def._endoderm"):
## longer object length is not a multiple of shorter object length

cowplot::plot_grid(p1, p2, ncol = 1)


ggsave(paste0(plot_dir, "mesenchyme_split.pdf"))

Clustering by Seurat with resolution = 0.6 yields 18 distinct clusters, not enough to differentiate the large number of different celltypes in this dataset.

DimPlot(rna_seurat, reduction = "umap", pt.size = .1, 
        group.by = "seurat_clusters", label = TRUE) +
  NoLegend()

Below, you can see how the earlier time points separate from the later time points. The number of counts is very homogenous, while the mitochondrial RNA percentage is higher and the number of features lower for E7.5 as already pointed out.

p1 <- DimPlot(rna_seurat, reduction = "umap", pt.size = .1, group.by = "sample")

p2 <- FeaturePlot(rna_seurat, reduction = "umap", pt.size = .1,
            features = "nCount_RNA") +
    scale_color_viridis_c() 
p3 <- FeaturePlot(rna_seurat, reduction = "umap", pt.size = .1, features = "mitochondrial_percent_RNA") +
    scale_color_viridis_c() 

p4 <- FeaturePlot(rna_seurat, reduction = "umap", pt.size = .1, features = "nFeature_RNA") +
    scale_color_viridis_c() 

gridExtra::grid.arrange(p1, p2, p3, p4, ncol = 2, nrow = 2)

Distribution of celltypes at different time points

Visualizing the cells at each timepoint in separate UMAPs shows how the distribution of celltypes changes as gastrulation proceeds. The heterogenous cell cluster present at E7.5 disappears at later time points. We can also see how no Erythroids are present at E7.5, Erythroid1 (and to lesser extend Erythroid2 and 3) appear at E8.0, while Eryhtroid3 are found to a higher extent at E8.75, which indicates that these cells correspond to different developmental stages.

DimPlot(rna_seurat, reduction = "umap", pt.size = 1, 
        group.by = "celltype.mapped", split.by = "orig.ident", ncol = 1, cols = col) +
  labs(title = "Celltypes at different time points")



ggsave(paste0(plot_dir, "celltypes_timepoints.pdf"))
p1 <- DimPlot(subset(rna_seurat, sample %in% c("E8.5_rep1", "E8.5_rep2", "E8.5_CRISPR_T_KO", "E8.5_CRISPR_T_WT")), 
        group.by = "celltype.mapped", split.by = "sample", ncol = 1, cols = col, pt.size = 1)
p1

We can see that nascent mesoderm, epiblast and primitive streak are only present at E7.5 and E7.75. Also, extraembryonice endoderm and ectoderm are highest and decrease with progressing gastrulation. Forebrain/Midbrain/Hindbrain, neural crest and neuromesodermal progenitor (NMP) cells are not present at E7.5, but emerge at E8.0 and are present at even higher percentage at E8.5. Also, the endothelium appears only at E8.0. The same is true for Allantois, erythroids (produce red blood cells, remain in bone marrow) and cardiomyocytes. Conversely, the number of extraembryonic ectoderm cells and extraembryonic endoderm). Similar results were seen in a scRNA-seq dataset [@Pijuan2019]


pal <- c("#FACB12", "#F6BFCB", "#B51D8D", "#65A83E","#0F4A9C")
# plot the frequency of each cell type at each embryonic stage
# all frequencies for one embryonic stage would add up to 0
rna_seurat@meta.data %>%
  #group_by(orig.ident, celltype.mapped) %>% 
  #summarise(Total = n()) %>% 
  #mutate(freq = Total/sum(Total)) %>% 
  ggplot(aes(x = celltype.mapped, fill = orig.ident), alpha =.7) +
  geom_bar(position = "fill") +
  #scale_fill_manual(values = pal) +
  #theme(axis.text.x = element_text(angle = 45, vjust = 0.8, hjust=1)) +
  scale_fill_brewer(palette="Set3") +
  guides(fill=guide_legend(title="timepoint")) +
  #scale_fill_brewer(palette="Set3") +
  labs(y = "percentage", x = "celltype") +
  theme(axis.text.x = element_text(angle = 45, hjust=1, size = 12),
        axis.text.y = element_text(size = 15),
        axis.title.x = element_blank(), # change size of axis title
        axis.title.y = element_text(size = 20),
        plot.title = element_text(hjust = 0.5, size = 25),
        legend.title = element_text(size = 12),
      panel.grid.major = element_line(colour = "grey"),   # Major grid lines
      panel.background = element_rect(fill = "white", colour = "black"),
      aspect.ratio = 0.4)

  
  
ggsave(paste0(plot_dir, "celltypes_timepoints_percentage.pdf"))
 
  
  
# rna_seurat@meta.data %>%
#   group_by(orig.ident, celltype.mapped) %>% 
#   summarise(Total = n()) %>% 
#   mutate(freq = Total/sum(Total)) %>% 
#   ggplot(aes(x = celltype.mapped, y = freq, fill = orig.ident)) +
#   geom_bar(position = "dodge", stat = "identity", alpha = .7) +
#   scale_fill_manual(values = pal) +
#   theme(axis.text.x = element_text(angle = 45, vjust = 0.8, hjust=1)) 

Save Seurat object

#saveRDS(rna_seurat, "/omics/groups/OE0533/internal/katharina/scDoRI/gastrulation_data_new/Kathi/rna_seurat")

#rna_seurat <- readRDS("/omics/groups/OE0533/internal/katharina/scDoRI/gastrulation_data_new/Kathi/rna_seurat")

#sce <- as.SingleCellExperiment(rna_seurat, assay = "RNA")


#writeH5AD(sce, "/omics/groups/OE0533/internal/katharina/scDoRI/gastrulation_data_new/Kathi/rna_anndata_from_seurat", X_name = "counts")

Marker genes of erythroid lineage cells

```#{r} markers <- FindAllMarkers(rna_seurat, only.pos = TRUE, min.pct = .25, logfc.threshold = .25)

```

scATAC-seq data

QC ATAC

proj <- loadArchRProject("/omics/groups/OE0533/internal/katharina/scDoRI/gastrulation_data_new/Kathi/01_original_subset/")

metadata <- getCellColData(proj) %>% as.data.frame()
metadata %>%
  ggplot() +
  geom_density2d_filled(aes(x=log10(nFrags_atac ), y=TSSEnrichment_atac), bins=20) +
  geom_hline(yintercept = 5, color="green", linetype="dashed") +
  geom_vline(xintercept = 3, color="green", linetype="dashed") +
  #geom_xsidedensity(aes(x=log10(pre_filter_meta$nFrags))) +
  #geom_ysidedensity(aes(y = pre_filter_meta$TSSEnrichment)) +
  facet_wrap(~sample) +
  theme(legend.position = "none") +
  labs(x = "Log10 Unique Fragments", y = "TSS Enrichment Score")

The scATAC-seq shows that E7.5 seems to be of lower quality, which we have already observed in the scRNA-seq. Potentially, the cells where simply in a worse condition when sequenced.

p1 <- metadata %>% 
  ggplot() +
  ggridges::geom_density_ridges(aes(x = TSSEnrichment_atac, y = Sample, fill = Sample),
                                alpha = .9) +
  scale_fill_brewer(palette="Set3") +
  theme(
      plot.title = element_text(hjust = 0.5),
      legend.position = "None", 
      panel.grid.major = element_line(colour = "grey"),   # Major grid lines
      #strip.background = element_rect(colour = "black", fill = "white"),
      panel.background = element_rect(fill = "white", colour = "black"))
  

p2 <- metadata %>% 
  ggplot() +
  geom_violin(aes(x = Sample, y = TSSEnrichment, fill = Sample), alpha = 0.9) +
  geom_boxplot(aes(x = Sample, y = TSSEnrichment,fill = Sample), alpha = 0.2) + 
  theme(legend.position = "none") +
  labs(title = "TSS Enrichment") +
  scale_fill_brewer(palette="Set3") +
  guides(fill=guide_legend(title="sample")) +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
        plot.title = element_text(hjust = 0.5),
        legend.position = "None", 
        panel.grid.major = element_line(colour = "grey"),   # Major grid lines
        #strip.background = element_rect(colour = "black", fill = "white"),
        panel.background = element_rect(fill = "white", colour = "black"))
  

cowplot::plot_grid(p2, p1, ncol = 2)

Plots for report


p1 <- metadata %>% 
  ggplot() +
  geom_violin(aes(x = Sample, y = TSSEnrichment, fill = Sample), alpha = 0.9) +
  geom_boxplot(aes(x = Sample, y = TSSEnrichment,fill = Sample), alpha = 0.2) + 
  theme(legend.position = "none") +
  labs(title = "TSS Enrichment") +
  scale_fill_brewer(palette="Set3") +
  guides(fill=guide_legend(title="sample")) +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
        plot.title = element_text(hjust = 0.5),
        legend.position = "None", 
        panel.grid.major = element_line(colour = "grey"),   # Major grid lines
        #strip.background = element_rect(colour = "black", fill = "white"),
        panel.background = element_rect(fill = "white", colour = "black"))

p2 <- metadata %>% 
  ggplot() +
  geom_violin(aes(x = Sample, y = nFrags_atac , fill = Sample), alpha = 0.6) +
  geom_boxplot(aes(x = Sample, y = nFrags_atac ,fill = Sample), alpha = 0.1) + 
  theme(legend.position = "none") +
  labs(title = "Number of unique Fragments", y = "#Fragments") +
  scale_fill_brewer(palette="Set3") +
  guides(fill=guide_legend(title="sample")) +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1, size = 15),
        axis.text.y = element_text(size = 15),
        axis.title.y = element_text(size = 20),
        plot.title = element_text(hjust = 0.5, size = 25),
        legend.position = "None", 
        panel.grid.major = element_line(colour = "grey"),   # Major grid lines
        #strip.background = element_rect(colour = "black", fill = "white"),
        panel.background = element_rect(fill = "white", colour = "black"))

  

cowplot::plot_grid(p1, p2, ncol = 2)


ggsave(paste0(plot_dir, "qc_atac.pdf"))
metadata %>% 
  ggplot() +
  geom_violin(aes(x = Sample, y = nFrags_atac , fill = Sample), alpha = 0.6) +
  geom_boxplot(aes(x = Sample, y = nFrags_atac ,fill = Sample), alpha = 0.1) + 
  theme(legend.position = "none") +
  labs(title = "Number of unique Fragments", y = "#Fragments") +
  scale_fill_brewer(palette="Set3") +
  guides(fill=guide_legend(title="sample")) +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
        plot.title = element_text(hjust = 0.5),
        legend.position = "None", 
        panel.grid.major = element_line(colour = "grey"),   # Major grid lines
        #strip.background = element_rect(colour = "black", fill = "white"),
        panel.background = element_rect(fill = "white", colour = "black"))

p1 <- atac_seurat@meta.data %>% 
  ggplot() +
  ggridges::geom_density_ridges(aes(x = nFrags_atac , y = Sample, fill = Sample),
                                alpha = .6) +
  scale_fill_brewer(palette="Set3") +
  theme(
    plot.title = element_text(hjust = 0.5),
    legend.position = "None", 
    panel.grid.major = element_line(colour = "grey"),   # Major grid lines
    #strip.background = element_rect(colour = "black", fill = "white"),
    panel.background = element_rect(fill = "white", colour = "black"))

p2 <- atac_seurat@meta.data %>% 
  ggplot() +
  geom_violin(aes(x = Sample, y = nFrags_atac , fill = Sample), alpha = 0.6) +
  geom_boxplot(aes(x = Sample, y = nFrags_atac ,fill = Sample), alpha = 0.1) + 
  theme(legend.position = "none") +
  labs(title = "Number of unique Fragments") +
  scale_fill_brewer(palette="Set3") +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
        plot.title = element_text(hjust = 0.5),
        legend.position = "None", 
        panel.grid.major = element_line(colour = "grey"),   # Major grid lines
        #strip.background = element_rect(colour = "black", fill = "white"),
        panel.background = element_rect(fill = "white", colour = "black"))
cowplot::plot_grid(p2, p1, ncol = 2)

Normalization & Dimensionality reduction ATAC

Latent Semantic Indexing

  1. TF-IDF normalization
  • normalize across cells (sequencing depth)
  • normalize across peak (higher values to more rare peaks)
  1. Select Top features
  2. Run SVD on selected features

```#{r} colSums()

atac_seurat <- RunTFIDF(atac_seurat) atac_seurat <- FindTopFeatures(atac_seurat) atac_seurat <- RunSVD(atac_seurat) ``` The first LSI component often captures sequencing depth. We will therefore remove it from downstream analysis. The correlation between sequencing depth and each LSI component is shown in the plot below.

#{r} DepthCor(atac_seurat)

Visualization

```#{r} atac_seurat <- RunUMAP(atac_seurat, reduction = "lsi", dims = 2:30, verbose = FALSE) aatac_seurat <- FindNeighbors(atac_seurat, reduction = "lsi", dims = 2:30, verbose = FALSE)

for Clsutering instead of Louvian SLM algorithm is used

atac_seurat <- FindClusters(atac_seurat, verbose = FALSE, algorithm = 3)

```

```#{r, fig.width = 15, fig.height=10}

DimPlot(atac_seurat, group.by = "celltype.mapped_seurat", reduction = "umap", pt.size = 1, cols = col) + labs(title = "scATAC-seq Celltype")

DimPlot(atac_seurat, group.by = "sample", reduction = "umap", pt.size = 1, cols = col) + labs(title = "scATAC-seq Celltype") ```

```#{r, fig.width=15, fig.height=10} DimPlot(rna_seurat , group.by = "celltype.mapped_seurat", pt.size = 1, cols = col, reduction = "umap") + labs(title = "scRNA-seq Celltype")

```

Lets have a look at whether the number of fragments is correlated to the number of counts in each celltype. This seems to be the case.

#{r, fig.width=10, fig.height=8} atac_seurat@meta.data %>% ggplot(aes(x = log10(nCount_originalexp ), y = log10(nFrags_atac))) + geom_point(alpha = .2, size = .2) + ggside::geom_xsidedensity() + ggside::geom_ysidedensity() + facet_wrap(~sample) + labs(x = "Log10 Counts", y = "log10 Unique Fragments")

#{r, fig.width=10, fig.height=10} atac_seurat@meta.data %>% ggplot(aes(x = log10(nCount_originalexp), y = log10(TSSEnrichment))) + geom_point(size = .2, alpha = .2) + ggside::geom_xsidedensity() + ggside::geom_ysidedensity() + facet_wrap(~sample)

```#{r} %>% ggplot() + geom_histogram(aes(x = PromoterRatio_atac))

%>% ggplot() + geom_histogram(aes(x = NucleosomeRatio_atac)) ```

#saveRDS(atac_seurat, "atac_Seurat_object")
#saveRDS(rna_seurat, "rna_Seurat_object")
LS0tCnRpdGxlOiAiUHJvY2Vzc2VkIHNjUk5BLXNlcSAmIHNjQVRBQy1zZXEgb2YgbW91c2UgZ2FzdHJ1bGF0aW9uIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogNQogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRoZW1lOiBjb3NtbwogICAgaGlnaGxpZ2h0OiB0ZXh0bWF0ZQotLS0KCgo8c3R5bGU+CmJvZHkgewp0ZXh0LWFsaWduOiBqdXN0aWZ5fQo8L3N0eWxlPgoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChjYWNoZSA9IEZBTFNFLCBhdXRvZGVwID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZSA9IFRSVUUsIG1lc3NhZ2UgPSBGQUxTRSkKa25pdHI6Om9wdHNfa25pdCRzZXQocm9vdC5kaXIgPSAiL29taWNzL2dyb3Vwcy9PRTA1MzMvaW50ZXJuYWwva2F0aGFyaW5hL3NjRG9SSS9nYXN0cnVsYXRpb25fZGF0YS8iKQpzZXR3ZCgiL29taWNzL2dyb3Vwcy9PRTA1MzMvaW50ZXJuYWwva2F0aGFyaW5hL3NjRG9SSS9nYXN0cnVsYXRpb25fZGF0YS8iKQoKc2V0LnNlZWQoMSkKYGBgCgoKCmBgYHtyfQpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMoewpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShTZXVyYXQpCmxpYnJhcnkoU2V1cmF0RGF0YSkKbGlicmFyeShzY2F0ZXIpCmxpYnJhcnkoemVsbGtvbnZlcnRlcikKbGlicmFyeShTaW5nbGVDZWxsRXhwZXJpbWVudCkKbGlicmFyeShFbnNEYi5NbXVzY3VsdXMudjc5KQpsaWJyYXJ5KFNpZ25hYykKbGlicmFyeShBcmNoUikKfSkKYGBgCgpgYGB7cn0KcGxvdF9kaXIgPC0gIi9vbWljcy9ncm91cHMvT0UwNTMzL2ludGVybmFsL2thdGhhcmluYS9zY0RvUkkvZ2FzdHJ1bGF0aW9uX2RhdGFfbmV3L0thdGhpL3Bsb3RzLyIKYGBgCgoKVGhlIGRhdGFzZXQgY29uc2lzdHMgb2YgbXVsdGlvbWUgZGF0YSAoc2NBVEFDLXNlcSAmIHNjUk5BLXNlcSkgZnJvbSBjZWxscyBhdCB0aGUgCnRpbWVwb2ludHMgRTcuNSwgRTcuNzUsIEU4LjAsIEU4LjUsIEU4Ljc1LiBBZGRpdGlvbmFsbHksIHRoZXJlIGlzIGRhdGEgZnJvbSBhIApDUklTUFIgS25vY2tvdXQgb2YgdGhlIHRyYW5zY3JpcHRpb24gZmFjdG9yIFQgd2hpY2ggaXMgaW1wb3J0YW50IGZvciB0aGUgZGV2ZWxvcG1lbnQKb2YgdGhlIG1lc29kZXJtIGxpbmVhZ2UuIExhc3RseSwgdGhlcmUgaXMgYSBDUklTUFIgd2lsZHR5cGUgc2FtcGxlIGFzIGEgY29udHJvbC4gIAoKCgpgYGB7ciwgcmVzdWx0cyA9ICJhc2lzIn0Kcm5hX2dhc3RyX1NFIDwtIHJlYWRSRFMoIi9vbWljcy9ncm91cHMvT0UwNTMzL2ludGVybmFsL2thdGhhcmluYS9zY0RvUkkvZ2FzdHJ1bGF0aW9uX2RhdGFfbmV3L3Byb2Nlc3NlZC9ybmEvU2luZ2xlQ2VsbEV4cGVyaW1lbnQucmRzIikKCiMgY29udmVydCB0byBzZXVyYXQgb2JqZWN0CnJuYV9zZXVyYXQgPC0gYXMuU2V1cmF0KHJuYV9nYXN0cl9TRSwgY291bnRzID0gImNvdW50cyIsIGRhdGEgPSAiY291bnRzIikKCgpwcm9qIDwtIGxvYWRBcmNoUlByb2plY3QoIi9vbWljcy9ncm91cHMvT0UwNTMzL2ludGVybmFsL2thdGhhcmluYS9zY0RvUkkvZ2FzdHJ1bGF0aW9uX2RhdGFfbmV3L3Byb2Nlc3NlZC9hdGFjL2FyY2hSLyIpCgptZXRhZGF0YSA8LSBnZXRDZWxsQ29sRGF0YShwcm9qKQoKbWV0YWRhdGEgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUKICBncm91cF9ieShzYW1wbGUpICU+JQogIHN1bW1hcmlzZShuID0gbigpKSAlPiUga25pdHI6OmthYmxlKCkKCm1ldGFkYXRhIDwtIG1ldGFkYXRhICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIAogIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKGNlbGx0eXBlLm1hcHBlZCkpICU+JQogIHJvd25hbWVzX3RvX2NvbHVtbigiY2VsbCIpICU+JQogIGRwbHlyOjpmaWx0ZXIoY2VsbCAlaW4lIGNvbG5hbWVzKHJuYV9zZXVyYXQpKSAlPiUKICBjb2x1bW5fdG9fcm93bmFtZXMoImNlbGwiKQoKcm5hX3NldXJhdCA8LSBybmFfc2V1cmF0Wywgcm93bmFtZXMobWV0YWRhdGEpXQoKcm5hX3NldXJhdCA8LSBBZGRNZXRhRGF0YShybmFfc2V1cmF0LCBtZXRhZGF0YSkKCgpybShybmFfZ2FzdHJfU0UpCnJtKHByb2opCmdjKHJlc2V0ID0gVFJVRSkKYGBgCgoKYGBge3J9CmF0YWNfcGVha3MgPC0gcmVhZEg1QUQoIi9vbWljcy9ncm91cHMvT0UwNTMzL2ludGVybmFsL2thdGhhcmluYS9zY0RvUkkvZ2FzdHJ1bGF0aW9uX2RhdGFfbmV3L3Byb2Nlc3NlZC9hdGFjL2FubmRhdGEvUGVha01hdHJpeC9QZWFrTWF0cml4X2FubmRhdGEuaDVhZCIpCgoKYXRhY19zZXVyYXQgPC0gYXMuU2V1cmF0KGF0YWNfcGVha3MsIGNvdW50cyA9ICJYIiwgZGF0YSA9ICJYIikKCgpybmFfc2V1cmF0IDwtIHJlYWRSRFMoIi9vbWljcy9ncm91cHMvT0UwNTMzL2ludGVybmFsL2thdGhhcmluYS9zY0RvUkkvZ2FzdHJ1bGF0aW9uX2RhdGFfbmV3L0thdGhpL3JuYV9zZXVyYXQiKQoKCnJtKGF0YWNfcGVha3MpCiNybShhdGFjX2dlbmVfc2NvcmVzKQpnYyhyZXNldCA9IFRSVUUpCgpgYGAKCiMgc2NSTkEtc2VxCgojIyBRdWFsdGl5IENvbnRyb2wKCgojIyMgRW1wdHkgRHJvcGxldHMKCmBgYHtyfQoKdGliYmxlKHNhbXBsZSA9IHJuYV9zZXVyYXRAbWV0YS5kYXRhJHNhbXBsZSwgdW1pX3Blcl9jZWxsID0gTWF0cml4Ojpjb2xTdW1zKHJuYV9zZXVyYXRAYXNzYXlzJFJOQUBjb3VudHMpKSAlPiUgCiAgYXJyYW5nZShzYW1wbGUsIGRlc2ModW1pX3Blcl9jZWxsKSkgJT4lIAogIGdyb3VwX2J5KHNhbXBsZSkgJT4lIAogIG11dGF0ZShpZHggPSBzZXFfYWxvbmcoc2FtcGxlKSkgJT4lIAogIG11dGF0ZShjdW1fdW1pX3Blcl9jZWxsID0gY3Vtc3VtKHVtaV9wZXJfY2VsbCkpICU+JSAKICBnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gaWR4LCB5ID0gY3VtX3VtaV9wZXJfY2VsbCkpICsKICBmYWNldF93cmFwKH5zYW1wbGUsIHNjYWxlcyA9ICJmaXhlZCIpICsKICBzY2FsZV95X2xvZzEwKCkgKyBzY2FsZV94X2xvZzEwKCkgKwogIHlsYWIoImN1bXVsYXRpdmUgVU1JIGNvdW50IikgKwogIHhsYWIoImluZGV4IikKCgpgYGAKCgoKRnJvbSB0aGUgcGxvdHMgYmVsb3cgaXQgc2VlbXMgdGhhdCBhbGwgY2VsbHMgd2l0aCBwZXJjZW50YWdlIG9mIG1pdG9jaG9uZHJpYWwgCmdlbmVzIGFib3ZlIDQwJSB3ZXJlIHJlbW92ZWQuIFRoZSBlYXJseSB0aW1lIHBvaW50cyBFNy41cmVwMS8yIGhhdmUgdGhlIGhpZ2hlc3QKcGVyY2VudGFnZSBvZiBtaXRvY2hvbmRyaWFsIGdlbmVzLiBFc3BlY2lhbGx5IEU3LjUgcmVwMiBzZWVtcyB0byBoYXZlIGEgaGlnaGVyIApwZXJjZW50YWdlIG9mIG1pdG9jaG9uZHJpYWwgZ2VuZXMuIENvbnZlcnNlbHksIHRoZSBzYW1lIHJlcGxpY2F0ZXMgZnJvbSBFNy41IApoYXZlIGEgbG93ZXIgbnVtYmVyIG9mIGZlYXR1cmVzIGFuZCBjb3VudHMuIFRoaXMgbWVhbnMgdGhhdCB0aGUgRTcuNSByZXAyIGFuZCB0bwphIGxlc3NlciBleHRlbnQgRTcuNSByZXAxIGFyZSBvZiBsb3dlciBxdWFsaXR5IGNvbXBhcmVkIHRvIHRoZSBvdGhlciBzYW1wbGVzLiBFOC43NSAKcmVwMS9yZXAyIHNlZW0gdG8gaGF2ZSB0aGUgaGlnaGVzdCBxdWFsaXR5LiAKCgpgYGB7ciwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTEwfQojcmVuYW1lIG1ldGFkYXRhCgp2YXJpYWJsZXMgPC0gYygibkZlYXR1cmVfUk5BIiwgIm5Db3VudF9STkEiLCAibWl0b2Nob25kcmlhbF9wZXJjZW50X1JOQSIsICJyaWJvc29tYWxfcGVyY2VudF9STkEiKQpwbG90cyA8LSBtYXAodmFyaWFibGVzLCBmdW5jdGlvbihuKXsKICBkZiA8LSBybmFfc2V1cmF0QG1ldGEuZGF0YSAlPiUKICAgIGFycmFuZ2Uoc2FtcGxlKSAKICBwbG90IDwtIGdncGxvdChkZikgKwogICAgZ2VvbV92aW9saW4oYWVzKHggPSBkZiAlPiUgcHVsbCgic2FtcGxlIiksIHkgPSBkZiAlPiUgcHVsbChuKSwKICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IGRmICU+JSBwdWxsKCJzYW1wbGUiKSksIGFscGhhID0gLjkpICsKICAgIGdlb21fYm94cGxvdChhZXMoeCA9IGRmICU+JSBwdWxsKCJzYW1wbGUiKSwgeSA9IGRmICU+JSBwdWxsKG4pLAogICAgICAgICAgICAgICAgICAgICBmaWxsID0gZGYgJT4lIHB1bGwoInNhbXBsZSIpKSwgYWxwaGEgPSAuMikgKwogICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iU2V0MyIpICsKICAgIHhsYWIoInNhbXBsZSIpICsKICAgIHlsYWIocGFzdGUwKG4pKSArCiAgICBsYWJzKHRpdGxlID0gcGFzdGUwKG4pKSArCiAgICBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQodGl0bGU9InNhbXBsZSIpKSArCiAgICB0aGVtZSgKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAyNSksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUsIGhqdXN0PTEsIHNpemUgPTE1KSwKICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJOb25lIiwgCiAgICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmV5IiksICAgIyBNYWpvciBncmlkIGxpbmVzCiAgICAgICAgICAjc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiYmxhY2siLCBmaWxsID0gIndoaXRlIiksCiAgICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvdXIgPSAiYmxhY2siKSkKICBwcmludChwbG90KQogIGdnc2F2ZShwYXN0ZTAocGxvdF9kaXIsICJfIiwgbiwgIl9xYy5wZGYiKSkKICBwcmludChwbG90KQoKfSkKCnByaW50KGdyaWRFeHRyYTo6Z3JpZC5hcnJhbmdlKGdyb2JzID0gcGxvdHMsIG5jb2wgPSAyKSkKCgoKYGBgCgojIyBDZWxsdHlwZXMKCmBgYHtyfQpwcmludChwYXN0ZTAoIlRoZXJlIGFyZSAiLCBsZW5ndGgodW5pcXVlKHJuYV9zZXVyYXRAbWV0YS5kYXRhJGNlbGx0eXBlLm1hcHBlZCkpLCAiIGNlbGx0eXBlcyBpbiB0aGUgZGF0YXNldCIpKQpgYGAKCgo8ZGV0YWlscz4gCjxzdW1tYXJ5PlRhYmxlIHdpdGggbnVtYmVyIG9mIGNlbGxzIHBlciBjZWxsdHlwZTwvc3VtbWFyeT4KCmBgYHtyfQpybmFfc2V1cmF0QG1ldGEuZGF0YSAlPiUgZ3JvdXBfYnkoY2VsbHR5cGUubWFwcGVkKSAlPiUgCiAgc3VtbWFyaXNlKG4gPSBuKCkpICU+JSBrbml0cjo6a2FibGUoY2FwdGlvbiA9ICJOdW1iZXIgb2YgY2VsbHMgZm9yIGVhY2ggY2VsbHR5cGVzIikKYGBgCgo8L2RldGFpbHM+CgoKYGBge3J9CmNvbFBhbGV0dGVfY2VsbHR5cGVzID0gYygnIzUzMkM4QScsCiAnI2MxOWY3MCcsCiAnI2Y5ZGVjZicsCiAnI2M5YTk5NycsCiAnI0I1MUQ4RCcsCiAnIzNGODRBQScsCiAnIzllNjc2MicsCiAnIzM1NEUyMycsCiAnI0YzOTdDMCcsCiAnI2ZmODkxYycsCiAnIzYzNTU0NycsCiAnI0M3MjIyOCcsCiAnI2Y3OTA4MycsCiAnI0VGNEUyMicsCiAnIzk4OTg5OCcsCiAnIzdGNjg3NCcsCiAnIzg4NzBhZCcsCiAnIzY0N2E0ZicsCiAnI0VGNUE5RCcsCiAnI0ZCQkU5MicsCiAnIzEzOTk5MicsCiAnI2NjNzgxOCcsCiAnI0RGQ0RFNCcsCiAnIzhFQzc5MicsCiAnI0M1OTRCRicsCiAnI0MzQzM4OCcsCiAnIzBGNEE5QycsCiAnI0ZBQ0IxMicsCiAnIzhEQjVDRScsCiAnIzFBMUExQScsCiAnI0M5RUJGQicsCiAnI0RBQkU5OScsCiAnIzY1QTgzRScsCiAnIzAwNTU3OScsCiAnI0NERTA4OCcsCiAnI2Y3Zjc5ZScsCiAnI0Y2QkZDQicpCgoKY2VsbHR5cGVzIDwtIChybmFfc2V1cmF0QG1ldGEuZGF0YSAlPiUgYXJyYW5nZShjZWxsdHlwZS5tYXBwZWQpICU+JQogICAgICAgICAgICAgICAgZ3JvdXBfYnkoY2VsbHR5cGUubWFwcGVkKSAlPiUgCiAgc3VtbWFyaXNlKG4gPSBuKCkpKSRjZWxsdHlwZS5tYXBwZWQKCgpjZWxsdHlwZXMKCmNvbCA8LSBzZXROYW1lcyhjb2xQYWxldHRlX2NlbGx0eXBlcywgY2VsbHR5cGVzKQpjb2xbIlBHQyJdIDwtICIjRkFDQjEyIgpjb2xbIlBhcmF4aWFsX21lc29kZXJtIl0gPC0gIiM4REI1Q0UiCmNvbFsiUGFyaWV0YWxfZW5kb2Rlcm0iXSA8LSAiIzFBMUExQSIgCmNvbFsiTmV1cmFsX2NyZXN0Il0gPC0gIiNDM0MzODgiCmNvbFsiTk1QIl0gPC0gIiM4RUM3OTIiCmNvbFsiTmFzY2VudF9tZXNvZGVybSJdIDwtICIjQzU5NEJGIgoKCiNjZWxsdHlwZXMgPC0gKHJuYV9zZXVyYXRAbWV0YS5kYXRhICU+JSBncm91cF9ieShjZWxsdHlwZS5tYXBwZWQpICU+JSAKICMgc3VtbWFyaXNlKG4gPSBuKCkpKSRjZWxsdHlwZS5tYXBwZWQKCiNjb2wgPC0gc2V0TmFtZXMoY29sUGFsZXR0ZV9jZWxsdHlwZXMsIGNlbGx0eXBlcykKYGBgCgoKYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02fQoKcm5hX3NldXJhdEBtZXRhLmRhdGEgJT4lIGdyb3VwX2J5KGNlbGx0eXBlLm1hcHBlZCkgJT4lIAogIHN1bW1hcmlzZShuID0gbigpKSAlPiUjIGtuaXRyOjprYWJsZShjYXB0aW9uID0gIk51bWJlciBvZiBjZWxscyBmb3IgZWFjaCBjZWxsdHlwZXMiKQogIGdncGxvdCgpICsgCiAgZ2VvbV9iYXIoYWVzICh4ID0gY2VsbHR5cGUubWFwcGVkLCB5ID0gbiwKICAgICAgICAgICAgICAgIGZpbGwgPSBjZWxsdHlwZS5tYXBwZWQpLCBzdGF0ID0gImlkZW50aXR5IikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbCkgKwogIGxhYnModGl0bGUgPSAiTnVtYmVyIG9mIGNlbGxzIHBlciBjZWxsdHlwZSIsIHkgPSAibnVtYmVyIG9mIGNlbGxzIiwgeCA9ICJjZWxsdHlwZSIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdD0xLCBzaXplID0gMTUpLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLCAjIGNoYW5nZSBzaXplIG9mIGF4aXMgdGl0bGUKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMjUpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJOb25lIiwgCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JleSIpLCAgICMgTWFqb3IgZ3JpZCBsaW5lcwogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG91ciA9ICJibGFjayIpLAogICAgICAgIGFzcGVjdC5yYXRpbyA9IDAuNCkKCmdnc2F2ZShwYXN0ZTAocGxvdF9kaXIsICJjZWxsdHlwZXMucGRmIikpCgpybmFfc2V1cmF0QG1ldGEuZGF0YSAlPiUgZ3JvdXBfYnkoc2FtcGxlKSAlPiUgCiAgc3VtbWFyaXNlKG4gPSBuKCkpICU+JSMga25pdHI6OmthYmxlKGNhcHRpb24gPSAiTnVtYmVyIG9mIGNlbGxzIGZvciBlYWNoIGNlbGx0eXBlcyIpCiAgZ2dwbG90KCkgKyAKICBnZW9tX2JhcihhZXMgKHggPSBzYW1wbGUsIHkgPSBuLAogICAgICAgICAgICAgICAgZmlsbCA9IHNhbXBsZSksIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iU2V0MyIpICsKICBsYWJzKHRpdGxlID0gIk51bWJlciBvZiBjZWxscyBwZXIgc2FtcGxlIiwgeSA9ICJudW1iZXIgb2YgY2VsbHMiLCB4ID0gInNhbXBsZSIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdD0xLCBzaXplID0gMTUpLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLCAjIGNoYW5nZSBzaXplIG9mIGF4aXMgdGl0bGUKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMjUpLAogICAgICBsZWdlbmQucG9zaXRpb24gPSAiTm9uZSIsIAogICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmV5IiksICAgIyBNYWpvciBncmlkIGxpbmVzCiAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG91ciA9ICJibGFjayIpLAogICAgICBhc3BlY3QucmF0aW8gPSAwLjQpCgpnZ3NhdmUocGFzdGUwKHBsb3RfZGlyLCAic2FtcGxlcy5wZGYiKSkKYGBgCgoKCiMjIE5vcm1hbGl6ZSAmIFNjYWxlCgoKCmBgYCN7cn0KZ2MocmVzZXQgPSBUUlVFKQpybmFfc2V1cmF0IDwtIHJuYV9zZXVyYXQgJT4lIAogIE5vcm1hbGl6ZURhdGEodmVyYm9zZSA9IEZBTFNFKSAlPiUgCiAgU2NhbGVEYXRhKHZlcmJvc2UgPSBGQUxTRSkgJT4lCiAgRmluZFZhcmlhYmxlRmVhdHVyZXModmVyYm9zZSA9IEZBTFNFKQoKI2dhc3RyX3NldXJhdEBhc3NheXMkUk5BQGRhdGFbMDoxMCwgMDoxMF0KYGBgCgoKIyMjIFBDQQoKSSB3aWxsIHByb2NlZWQgd2l0aCAxNSBQQ3MuCgpgYGB7cn0Kcm5hX3NldXJhdCA8LSBSdW5QQ0Eocm5hX3NldXJhdCwgZmVhdHVyZXMgPSBWYXJpYWJsZUZlYXR1cmVzKHJuYV9zZXVyYXQpLAogICAgICAgICAgICAgdmVyYm9zZSA9IEZBTFNFKQoKRWxib3dQbG90KHJuYV9zZXVyYXQpCmBgYAoKYGBge3J9CnBjYV9wbG90cyA8LSBjb21wcmVoZW5yOjp0b19saXN0KGZvciAoaSBpbiAxOjE1KQogIERpbVBsb3Qocm5hX3NldXJhdCwgcmVkdWN0aW9uID0gInBjYSIsIGRpbXMgPSBpOihpKzEpKSArCiAgICB0aGVtZSgpKQoKI3BjYV9wbG90cwojZ3JpZEV4dHJhOjpncmlkLmFycmFuZ2UodW5saXN0KHBjYV9wbG90cyksIG5jb2wgPSAzLCBucm93ID0gNSkKCmBgYAoKIyMgQ2x1c3RlcmluZwoKVHJ5aW5nIGEgZGlmZmVyZW50IHJlc29sdXRpb24gZm9yIHRoZSBjbHVzdGVyaW5nIHRvIHNlZSBpZiB0aGUgTWVzZW5jaHltZSB3aWxsIApzdGlsbCBzZXBhcmF0ZS4KCmBgYCN7cn0Kcm5hX3NldXJhdCA8LSBGaW5kTmVpZ2hib3JzKHJuYV9zZXVyYXQsIHZlcmJvc2UgPSBGQUxTRSkKcm5hX3NldXJhdCA8LSBGaW5kQ2x1c3RlcnMocm5hX3NldXJhdCwgdmVyYm9zZSA9IEZBTFNFLCByZXNvbHV0aW9uID0gMC42KQpybmFfc2V1cmF0IDwtIFJ1blVNQVAocm5hX3NldXJhdCwgdmVyYm9zZSA9IEZBTFNFLCBkaW1zID0gMToxNSkKYGBgCgoKIyMgVmlzdWFsaXphdGlvbgoKCgoKVGhlcmUgYXJlIHR3byBwb3NzaWJpbGl0aWVzIHRvIHByb2NlZWQgd2l0aCBjZWxsdHlwZSBhbm5vdGF0aW9uczoKCgpJbiB0aGUgcGxvdCBiZWxvdyB5b3UgY2FuIHNlZSB0aGF0IHRoZSBNZXNlbmNoeW1lIHNlcGFyYXRlcyBpbnRvIHR3byBjbHVzdGVycywgYXMKd2VsbCBhcyB0aGUgZ3V0IGFuZCBoZW1hdG9lbmRvdGhlbGlhbCBwcm9nZW5pdG9ycywKZXZlbiB0aG91Z2ggdGhlIGNlbGxzIGJlbG9uZyB0byB0aGUgc2FtZSBjZWxsdHlwZS4gVGhlcmVmb3JlIEkgdmlzdWFsaXplZCB0aGUgCk1lc2VuY2h5bWUgY2VsbHMgYW5kIGd1dCBjZWxscyBhY2NvcmRpbmcgdG8gdGhlaXIgcmVzcGVjdGl2ZSB0aW1lIHBvaW50IGFuZCByZXBsaWNhdGUgYmVsb3cuIEl0IApiZWNvbWVzIGV2aWRlbnQgdGhhdCB0aGUgTWVzZW5jaHltZSBzZXBhcmF0ZSBpbnRvIEU3LjUgYW5kIEU4LjAsIEU4LjUsIEU4Ljc1LiBUaGVyZWZvcmUsCnRoZSBzZXBhcmF0aW9uIGlzIHByb2JhYmx5IGEgYmF0Y2ggZWZmZWN0IGNvcnJlc3BvbmRpbmcgdG8gZGlmZmVyZW50IHNpZ25hdHVyZXMgCmF0IGRpZmZlcmVudCB0aW1lIHBvaW50cy4gVGhpcyBjb3VsZCBhbHNvIGJlIGR1ZSB0byBiaW9sb2dpY2FsIGRpZmZlcmVuY2VzLCBob3dldmVyLCAKd2Ugc2hvdWxkIGtlZXAgaW4gbWluZCB0aGF0IEU3LjUgd2FzIGFsc28gdGhlCnRpbWUgcG9pbnQgd2l0aCBsb3dlc3QgcXVhbGl0eSBvZiBjZWxscy4gCgpUaGVyZSBpcyBvbmUgY2x1c3RlciB3aGljaCBjb250YWlucyBhIHZlcnkgaGV0ZXJvZ2VuZW91cyBwb3B1bGF0aW9uIG9mIGNlbGxzLApuYW1lbHkgbWl4ZWQgJiBuYXNjZW50IG1lc29kZXJtLCBjYXVkYWwgJiByb3N0cmFsIG5ldXJvZWN0b2Rlcm0sIHByaW1pdGl2ZSBzdHJlYWssIApjYXVkYWwgZXBpYmxhc3QgYW5kIGVwaWJsYXN0LiBBcyB3ZSB3aWxsIHNlZSBsYXRlciBvbiwgdGhlc2UgYXJlIHByaW1hcmlseSBlYXJseSBjZWxsdHlwZXMKZm91bmQgYXQgRTcuNSwgd2hpY2ggYXJlIG5vdCBwcmVzZW50IGF0IGxhdGVyIHRpbWVwb2ludHMgYW55bW9yZS4KCmBgYHtyfQojIGFkZCB1bWFwIGNvb3JkaW5hdGVzIHRvIG1ldGFkYXRhIGZvciBwbG90dGluZwptZXRhZGF0YSA8LSBybmFfc2V1cmF0QG1ldGEuZGF0YQptZXRhZGF0YSA8LSBtZXRhZGF0YSAlPiUgbXV0YXRlKHVtYXAxID0gcm5hX3NldXJhdFtbInVtYXAiXV1AY2VsbC5lbWJlZGRpbmdzWywgMV0sIAogICAgICAgICAgICAgICAgICAgIHVtYXAyID0gcm5hX3NldXJhdFtbInVtYXAiXV1AY2VsbC5lbWJlZGRpbmdzWywgMl0pCmBgYAoKCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9Nn0KCm1ldGFkYXRhICU+JSAKZ2dwbG90KCkgKwpnZW9tX3BvaW50KGFlcyh4ID0gdW1hcDEsIHkgPSB1bWFwMiwgCiAgICAgICAgICAgICAgIGNvbCA9IGNlbGx0eXBlLm1hcHBlZCksICBzaXplID0gLjYpICsKICBndWlkZXMoY29sPWd1aWRlX2xlZ2VuZCh0aXRsZT0iQ2VsbHR5cGUiLCBvdmVycmlkZS5hZXMgPSBsaXN0KHNpemUgPSA1KSkpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sKSsKICB4bGFiKCJVTUFQMSIpICsKICB5bGFiKCJVTUFQMiIpICsKICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwgIyBjaGFuZ2Ugc2l6ZSBvZiBheGlzIHRpdGxlCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksICMgY2hhbmdlIHNpemUgb2YgYXhpcyB0aXRsZQogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE1KSwgIyBjaGFuZ2Ugc2lleiBvZiBsZWdlbmQgdGl0bGUKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSwgIyBjaGFuZ2Ugc2l6ZSBvZiBsZWdlbmQgdGV4dAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG91ciA9ICJibGFjayIpLCAjIG1ha2UgYmFja2dyb3VuZCB3aGl0ZQogICAgICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BKSwgIyByZW1vdmUgYmFja2dyb3VuZCBmaWxsIGluIGxlZ2VuZAogICAgICAgIGFzcGVjdC5yYXRpbyA9IDEpICMgbWFrZSBwbG90IHF1YWRyYXRpYwoKCmdnc2F2ZShwYXN0ZTAocGxvdF9kaXIsICJjZWxsdHlwZV9wY2EucGRmIikpCmBgYAoKCgpgYGB7cixmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9Nn0KbWV0YWRhdGEgJT4lIApnZ3Bsb3QoKSArCmdlb21fcG9pbnQoYWVzKHggPSB1bWFwMSwgeSA9IHVtYXAyLCAKICAgICAgICAgICAgICAgY29sID0gc2FtcGxlKSwgIHNpemUgPSAuNCkgKwogIGd1aWRlcyhjb2w9Z3VpZGVfbGVnZW5kKHRpdGxlPSJTYW1wbGUiLCBvdmVycmlkZS5hZXMgPSBsaXN0KHNpemUgPSA1KSkpICsKICAjc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDMiKSArCiAgeGxhYigiVU1BUDEiKSArCiAgeWxhYigiVU1BUDIiKSArCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTUpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG91ciA9ICJibGFjayIpLAogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpLAogICAgICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BKSwKICAgICAgICBhc3BlY3QucmF0aW8gPSAxKQoKZ2dzYXZlKHBhc3RlMChwbG90X2RpciwgInNhbXBsZV9wY2EucGRmIikpCgpgYGAKCmBgYHtyLGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02fQptZXRhZGF0YSAlPiUgCmdncGxvdCgpICsKZ2VvbV9wb2ludChhZXMoeCA9IHVtYXAxLCB5ID0gdW1hcDIsIAogICAgICAgICAgICAgICBjb2wgPSByaWJvc29tYWxfcGVyY2VudF9STkEpLCAgc2l6ZSA9IC40KSArCiAgZ3VpZGVzKGNvbD1ndWlkZV9sZWdlbmQodGl0bGU9IiUgUmlib3NvbWFsIGdlbmVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgb3ZlcnJpZGUuYWVzID0gbGlzdChzaXplID0gNSkpKSArCiAgc2NhbGVfY29sb3JfdmlyaWRpc19jKCkgKwogIHhsYWIoIlVNQVAxIikgKwogIHlsYWIoIlVNQVAyIikgKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE1KSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvdXIgPSAiYmxhY2siKSwKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSwKICAgICAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSksCiAgICAgICAgYXNwZWN0LnJhdGlvID0gMSkKCmdnc2F2ZShwYXN0ZTAocGxvdF9kaXIsICJyaWJvc29tYWxfcGNhLnBkZiIpKQoKYGBgCgpgYGB7cixmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9Nn0KbWV0YWRhdGEgJT4lIApnZ3Bsb3QoKSArCmdlb21fcG9pbnQoYWVzKHggPSB1bWFwMSwgeSA9IHVtYXAyLCAKICAgICAgICAgICAgICAgY29sID0gbWl0b2Nob25kcmlhbF9wZXJjZW50X1JOQSksICBzaXplID0gLjQpICsKICBndWlkZXMoY29sPWd1aWRlX2xlZ2VuZCh0aXRsZT0iJSBNaXRvY2hvbmRyaWFsIGdlbmVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgb3ZlcnJpZGUuYWVzID0gbGlzdChzaXplID0gNSkpKSArCiAgc2NhbGVfY29sb3JfdmlyaWRpc19jKCkgKwogIHhsYWIoIlVNQVAxIikgKwogIHlsYWIoIlVNQVAyIikgKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE1KSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvdXIgPSAiYmxhY2siKSwKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSwKICAgICAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSksCiAgICAgICAgYXNwZWN0LnJhdGlvID0gMSkKCmdnc2F2ZShwYXN0ZTAocGxvdF9kaXIsICJtaXRvY2hvbmRyaWFsX3BjYS5wZGYiKSkKCmBgYAoKCmBgYHtyLGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02fQptZXRhZGF0YSAlPiUgCmdncGxvdCgpICsKZ2VvbV9wb2ludChhZXMoeCA9IHVtYXAxLCB5ID0gdW1hcDIsIAogICAgICAgICAgICAgICBjb2wgPSBuQ291bnRfUk5BKSwgIHNpemUgPSAuNCkgKwogIGd1aWRlcyhjb2w9Z3VpZGVfbGVnZW5kKHRpdGxlPSIjQ291bnRzIiwgb3ZlcnJpZGUuYWVzID0gbGlzdChzaXplID0gNSkpKSArCiAgc2NhbGVfY29sb3JfdmlyaWRpc19jKCkgKwogIHhsYWIoIlVNQVAxIikgKwogIHlsYWIoIlVNQVAyIikgKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE1KSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvdXIgPSAiYmxhY2siKSwKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSwKICAgICAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSksCiAgICAgICAgYXNwZWN0LnJhdGlvID0gMSkKCmdnc2F2ZShwYXN0ZTAocGxvdF9kaXIsICJjb3VudHNfcGNhLnBkZiIpKQoKYGBgCgpgYGB7cixmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9Nn0KbWV0YWRhdGEgJT4lIApnZ3Bsb3QoKSArCmdlb21fcG9pbnQoYWVzKHggPSB1bWFwMSwgeSA9IHVtYXAyLCAKICAgICAgICAgICAgICAgY29sID0gbkZlYXR1cmVfUk5BKSwgIHNpemUgPSAuNCkgKwogIGd1aWRlcyhjb2w9Z3VpZGVfbGVnZW5kKHRpdGxlPSIjRmVhdHVyZXMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBvdmVycmlkZS5hZXMgPSBsaXN0KHNpemUgPSA1KSkpICsKICBzY2FsZV9jb2xvcl92aXJpZGlzX2MoKSArCiAgeGxhYigiVU1BUDEiKSArCiAgeWxhYigiVU1BUDIiKSArCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTUpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG91ciA9ICJibGFjayIpLAogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpLAogICAgICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BKSwKICAgICAgICBhc3BlY3QucmF0aW8gPSAxKQoKZ2dzYXZlKHBhc3RlMChwbG90X2RpciwgImZlYXR1cmVzX3BjYS5wZGYiKSkKCmBgYAoKYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodCA9IDEwfQpEaW1QbG90KHJuYV9zZXVyYXQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIAogICAgICAgIGdyb3VwLmJ5ID0gImNlbGx0eXBlLm1hcHBlZCIsIGNvbHMgPSBjb2wpICMsIGxhYmVsID0gVFJVRSwgcmVwZWwgPSBUUlVFKSArCmBgYAoKCmBgYHtyLCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQ9MTV9CnAxIDwtIERpbVBsb3Qoc3Vic2V0KHJuYV9zZXVyYXQsIGNlbGx0eXBlLm1hcHBlZCA9PSAiTWVzZW5jaHltZSIpLCAKICAgICAgICBncm91cC5ieSA9ICJzYW1wbGUiKSArIGxhYnModGl0bGUgPSAiTWVzZW5jaHltZSIpCnAyIDwtIERpbVBsb3Qoc3Vic2V0KHJuYV9zZXVyYXQsIGNlbGx0eXBlLm1hcHBlZCA9PSBjKCJHdXQiLCAiVmlzY2VyYWxfZW5kb2Rlcm0iLCAiRGVmLl9lbmRvZGVybSIpKSwgCiAgICAgICAgZ3JvdXAuYnkgPSAic2FtcGxlIikgKyBsYWJzKHRpdGxlID0gIkd1dCwgVmlzY2VyYWwgZW5kb2Rlcm0sIERlZmluaXRpdmUgZW5kb2Rlcm0iKQoKcDMgPC0gcDEgPC0gRGltUGxvdChzdWJzZXQocm5hX3NldXJhdCwgY2VsbHR5cGUubWFwcGVkID09ICJNZXNlbmNoeW1lIiksIAogICAgICAgIGdyb3VwLmJ5ID0gImNlbGx0eXBlLm1hcHBlZCIpICsgbGFicyh0aXRsZSA9ICJNZXNlbmNoeW1lIikKCnA0IDwtICBEaW1QbG90KHN1YnNldChybmFfc2V1cmF0LCBjZWxsdHlwZS5tYXBwZWQgPT0gYygiR3V0IiwgIlZpc2NlcmFsX2VuZG9kZXJtIiwgIkRlZi5fZW5kb2Rlcm0iKSksIAogICAgICAgIGdyb3VwLmJ5ID0gImNlbGx0eXBlLm1hcHBlZCIpICsgbGFicyh0aXRsZSA9ICJHdXQsIFZpc2NlcmFsIGVuZG9kZXJtLCBEZWZpbml0aXZlIGVuZG9kZXJtIikKY293cGxvdDo6cGxvdF9ncmlkKHAxLCBwMiwgcDMsIHA0LCBuY29sID0gMikKCmdnc2F2ZShwYXN0ZTAocGxvdF9kaXIsICJtZXNlbmNoeW1lLnBkZiIpKQoKYGBgCgoKYGBge3IsZmlnLndpZHRoPTIwLCBmaWcuaGVpZ2h0PTEwfQoKcDEgPC0gRGltUGxvdChzdWJzZXQocm5hX3NldXJhdCwgY2VsbHR5cGUubWFwcGVkID09ICJNZXNlbmNoeW1lIiksIAogICAgICAgIHNwbGl0LmJ5ICA9ICJzYW1wbGUiKQoKcDIgPC0gRGltUGxvdChzdWJzZXQocm5hX3NldXJhdCwgY2VsbHR5cGUubWFwcGVkID09IGMoIkd1dCIsICJWaXNjZXJhbF9lbmRvZGVybSIsICJEZWYuX2VuZG9kZXJtIikpLCAKICAgICAgICBzcGxpdC5ieSAgPSAic2FtcGxlIikKCmNvd3Bsb3Q6OnBsb3RfZ3JpZChwMSwgcDIsIG5jb2wgPSAxKQoKZ2dzYXZlKHBhc3RlMChwbG90X2RpciwgIm1lc2VuY2h5bWVfc3BsaXQucGRmIikpCgpgYGAKCgoKCkNsdXN0ZXJpbmcgYnkgU2V1cmF0IHdpdGggcmVzb2x1dGlvbiA9IDAuNiB5aWVsZHMgMTggZGlzdGluY3QgY2x1c3RlcnMsIG5vdCBlbm91Z2gKdG8gZGlmZmVyZW50aWF0ZSB0aGUgbGFyZ2UgbnVtYmVyIG9mIGRpZmZlcmVudCBjZWxsdHlwZXMgaW4gdGhpcyBkYXRhc2V0LgoKYGBge3J9CkRpbVBsb3Qocm5hX3NldXJhdCwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gLjEsIAogICAgICAgIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsIGxhYmVsID0gVFJVRSkgKwogIE5vTGVnZW5kKCkKYGBgCgpCZWxvdywgeW91IGNhbiBzZWUgaG93IHRoZSBlYXJsaWVyIHRpbWUgcG9pbnRzIHNlcGFyYXRlIGZyb20gdGhlIGxhdGVyIHRpbWUgCnBvaW50cy4gVGhlIG51bWJlciBvZiBjb3VudHMgaXMgdmVyeSBob21vZ2Vub3VzLCB3aGlsZSB0aGUgbWl0b2Nob25kcmlhbCBSTkEgCnBlcmNlbnRhZ2UgaXMgaGlnaGVyIGFuZCB0aGUgbnVtYmVyIG9mIGZlYXR1cmVzIGxvd2VyIGZvciBFNy41IGFzIGFscmVhZHkgcG9pbnRlZCBvdXQuCgpgYGB7ciwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTEwfQpwMSA8LSBEaW1QbG90KHJuYV9zZXVyYXQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IC4xLCBncm91cC5ieSA9ICJzYW1wbGUiKQoKcDIgPC0gRmVhdHVyZVBsb3Qocm5hX3NldXJhdCwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gLjEsCiAgICAgICAgICAgIGZlYXR1cmVzID0gIm5Db3VudF9STkEiKSArCiAgICBzY2FsZV9jb2xvcl92aXJpZGlzX2MoKSAKcDMgPC0gRmVhdHVyZVBsb3Qocm5hX3NldXJhdCwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gLjEsIGZlYXR1cmVzID0gIm1pdG9jaG9uZHJpYWxfcGVyY2VudF9STkEiKSArCiAgICBzY2FsZV9jb2xvcl92aXJpZGlzX2MoKSAKCnA0IDwtIEZlYXR1cmVQbG90KHJuYV9zZXVyYXQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IC4xLCBmZWF0dXJlcyA9ICJuRmVhdHVyZV9STkEiKSArCiAgICBzY2FsZV9jb2xvcl92aXJpZGlzX2MoKSAKCmdyaWRFeHRyYTo6Z3JpZC5hcnJhbmdlKHAxLCBwMiwgcDMsIHA0LCBuY29sID0gMiwgbnJvdyA9IDIpCgoKYGBgCgoKIyMgRGlzdHJpYnV0aW9uIG9mIGNlbGx0eXBlcyBhdCBkaWZmZXJlbnQgdGltZSBwb2ludHMKCgpWaXN1YWxpemluZyB0aGUgY2VsbHMgYXQgZWFjaCB0aW1lcG9pbnQgaW4gc2VwYXJhdGUgVU1BUHMgc2hvd3MgaG93IHRoZQpkaXN0cmlidXRpb24gb2YgY2VsbHR5cGVzIGNoYW5nZXMgYXMgZ2FzdHJ1bGF0aW9uIHByb2NlZWRzLiBUaGUgaGV0ZXJvZ2Vub3VzIApjZWxsIGNsdXN0ZXIgcHJlc2VudCBhdCBFNy41IGRpc2FwcGVhcnMgYXQgbGF0ZXIgdGltZSBwb2ludHMuIFdlIGNhbiBhbHNvIHNlZSBob3cKbm8gRXJ5dGhyb2lkcyBhcmUgcHJlc2VudCBhdCBFNy41LApFcnl0aHJvaWQxIChhbmQgdG8gbGVzc2VyIGV4dGVuZCBFcnl0aHJvaWQyIGFuZCAzKSBhcHBlYXIgYXQgRTguMCwgd2hpbGUgRXJ5aHRyb2lkMyAKYXJlIGZvdW5kIHRvIGEgaGlnaGVyIGV4dGVudAphdCBFOC43NSwgd2hpY2ggaW5kaWNhdGVzIHRoYXQgdGhlc2UgY2VsbHMgY29ycmVzcG9uZCB0byBkaWZmZXJlbnQgZGV2ZWxvcG1lbnRhbCAKc3RhZ2VzLiAKCmBgYHtyLCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQ9MjB9CkRpbVBsb3Qocm5hX3NldXJhdCwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgCiAgICAgICAgZ3JvdXAuYnkgPSAiY2VsbHR5cGUubWFwcGVkIiwgc3BsaXQuYnkgPSAib3JpZy5pZGVudCIsIG5jb2wgPSAxLCBjb2xzID0gY29sKSArCiAgbGFicyh0aXRsZSA9ICJDZWxsdHlwZXMgYXQgZGlmZmVyZW50IHRpbWUgcG9pbnRzIikKCgpnZ3NhdmUocGFzdGUwKHBsb3RfZGlyLCAiY2VsbHR5cGVzX3RpbWVwb2ludHMucGRmIikpCgpgYGAKCgpgYGB7ciwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTIwfQpwMSA8LSBEaW1QbG90KHN1YnNldChybmFfc2V1cmF0LCBzYW1wbGUgJWluJSBjKCJFOC41X3JlcDEiLCAiRTguNV9yZXAyIiwgIkU4LjVfQ1JJU1BSX1RfS08iLCAiRTguNV9DUklTUFJfVF9XVCIpKSwgCiAgICAgICAgZ3JvdXAuYnkgPSAiY2VsbHR5cGUubWFwcGVkIiwgc3BsaXQuYnkgPSAic2FtcGxlIiwgbmNvbCA9IDEsIGNvbHMgPSBjb2wsIHB0LnNpemUgPSAxKQpwMQpgYGAKCgoKCldlIGNhbiBzZWUgdGhhdCBuYXNjZW50IG1lc29kZXJtLCBlcGlibGFzdCBhbmQgcHJpbWl0aXZlIHN0cmVhayBhcmUgb25seSBwcmVzZW50IAphdCBFNy41IGFuZCBFNy43NS4gQWxzbywgZXh0cmFlbWJyeW9uaWNlIGVuZG9kZXJtIGFuZCBlY3RvZGVybSBhcmUgaGlnaGVzdCBhbmQgZGVjcmVhc2UgCndpdGggcHJvZ3Jlc3NpbmcgZ2FzdHJ1bGF0aW9uLiBGb3JlYnJhaW4vTWlkYnJhaW4vSGluZGJyYWluLCBuZXVyYWwgY3Jlc3QgYW5kIApuZXVyb21lc29kZXJtYWwgcHJvZ2VuaXRvciAoTk1QKSBjZWxscyBhcmUgbm90IHByZXNlbnQgYXQgCkU3LjUsIGJ1dCBlbWVyZ2UgYXQgRTguMCBhbmQgYXJlIHByZXNlbnQgYXQgZXZlbiBoaWdoZXIgcGVyY2VudGFnZSBhdCBFOC41LiBBbHNvLAp0aGUgZW5kb3RoZWxpdW0gYXBwZWFycyBvbmx5IGF0IEU4LjAuIFRoZSAKc2FtZSBpcyB0cnVlIGZvciBBbGxhbnRvaXMsIGVyeXRocm9pZHMgKHByb2R1Y2UgcmVkIGJsb29kIGNlbGxzLCByZW1haW4gaW4gYm9uZQptYXJyb3cpIGFuZCBjYXJkaW9teW9jeXRlcy4gIENvbnZlcnNlbHksIHRoZSBudW1iZXIKb2YgZXh0cmFlbWJyeW9uaWMgZWN0b2Rlcm0gY2VsbHMgYW5kIGV4dHJhZW1icnlvbmljIGVuZG9kZXJtKS4gU2ltaWxhciByZXN1bHRzCndlcmUgc2VlbiBpbiBhIHNjUk5BLXNlcSBkYXRhc2V0IFtAUGlqdWFuMjAxOV0KCgpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTZ9CgpwYWwgPC0gYygiI0ZBQ0IxMiIsICIjRjZCRkNCIiwgIiNCNTFEOEQiLCAiIzY1QTgzRSIsIiMwRjRBOUMiKQojIHBsb3QgdGhlIGZyZXF1ZW5jeSBvZiBlYWNoIGNlbGwgdHlwZSBhdCBlYWNoIGVtYnJ5b25pYyBzdGFnZQojIGFsbCBmcmVxdWVuY2llcyBmb3Igb25lIGVtYnJ5b25pYyBzdGFnZSB3b3VsZCBhZGQgdXAgdG8gMApybmFfc2V1cmF0QG1ldGEuZGF0YSAlPiUKICAjZ3JvdXBfYnkob3JpZy5pZGVudCwgY2VsbHR5cGUubWFwcGVkKSAlPiUgCiAgI3N1bW1hcmlzZShUb3RhbCA9IG4oKSkgJT4lIAogICNtdXRhdGUoZnJlcSA9IFRvdGFsL3N1bShUb3RhbCkpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBjZWxsdHlwZS5tYXBwZWQsIGZpbGwgPSBvcmlnLmlkZW50KSwgYWxwaGEgPS43KSArCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsKICAjc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsKSArCiAgI3RoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIHZqdXN0ID0gMC44LCBoanVzdD0xKSkgKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGU9IlNldDMiKSArCiAgZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPSJ0aW1lcG9pbnQiKSkgKwogICNzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJTZXQzIikgKwogIGxhYnMoeSA9ICJwZXJjZW50YWdlIiwgeCA9ICJjZWxsdHlwZSIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdD0xLCBzaXplID0gMTIpLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLCAjIGNoYW5nZSBzaXplIG9mIGF4aXMgdGl0bGUKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMjUpLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmV5IiksICAgIyBNYWpvciBncmlkIGxpbmVzCiAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG91ciA9ICJibGFjayIpLAogICAgICBhc3BlY3QucmF0aW8gPSAwLjQpCiAgCiAgCmdnc2F2ZShwYXN0ZTAocGxvdF9kaXIsICJjZWxsdHlwZXNfdGltZXBvaW50c19wZXJjZW50YWdlLnBkZiIpKQogCiAgCiAgCiMgcm5hX3NldXJhdEBtZXRhLmRhdGEgJT4lCiMgICBncm91cF9ieShvcmlnLmlkZW50LCBjZWxsdHlwZS5tYXBwZWQpICU+JSAKIyAgIHN1bW1hcmlzZShUb3RhbCA9IG4oKSkgJT4lIAojICAgbXV0YXRlKGZyZXEgPSBUb3RhbC9zdW0oVG90YWwpKSAlPiUgCiMgICBnZ3Bsb3QoYWVzKHggPSBjZWxsdHlwZS5tYXBwZWQsIHkgPSBmcmVxLCBmaWxsID0gb3JpZy5pZGVudCkpICsKIyAgIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIsIGFscGhhID0gLjcpICsKIyAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhbCkgKwojICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgdmp1c3QgPSAwLjgsIGhqdXN0PTEpKSAKYGBgCgoKCjxkZXRhaWxzPiAKPHN1bW1hcnk+U2F2ZSBTZXVyYXQgb2JqZWN0PC9zdW1tYXJ5PgoKYGBge3J9CiNzYXZlUkRTKHJuYV9zZXVyYXQsICIvb21pY3MvZ3JvdXBzL09FMDUzMy9pbnRlcm5hbC9rYXRoYXJpbmEvc2NEb1JJL2dhc3RydWxhdGlvbl9kYXRhX25ldy9LYXRoaS9ybmFfc2V1cmF0IikKCiNybmFfc2V1cmF0IDwtIHJlYWRSRFMoIi9vbWljcy9ncm91cHMvT0UwNTMzL2ludGVybmFsL2thdGhhcmluYS9zY0RvUkkvZ2FzdHJ1bGF0aW9uX2RhdGFfbmV3L0thdGhpL3JuYV9zZXVyYXQiKQoKI3NjZSA8LSBhcy5TaW5nbGVDZWxsRXhwZXJpbWVudChybmFfc2V1cmF0LCBhc3NheSA9ICJSTkEiKQoKCiN3cml0ZUg1QUQoc2NlLCAiL29taWNzL2dyb3Vwcy9PRTA1MzMvaW50ZXJuYWwva2F0aGFyaW5hL3NjRG9SSS9nYXN0cnVsYXRpb25fZGF0YV9uZXcvS2F0aGkvcm5hX2FubmRhdGFfZnJvbV9zZXVyYXQiLCBYX25hbWUgPSAiY291bnRzIikKYGBgCgo8L2RldGFpbHM+CgoKCiMjIE1hcmtlciBnZW5lcyBvZiBlcnl0aHJvaWQgbGluZWFnZSBjZWxscwoKYGBgI3tyfQptYXJrZXJzIDwtIEZpbmRBbGxNYXJrZXJzKHJuYV9zZXVyYXQsIG9ubHkucG9zID0gVFJVRSwKICAgICAgICAgICAgICAgbWluLnBjdCA9IC4yNSwgbG9nZmMudGhyZXNob2xkID0gLjI1KQoKYGBgCgoKCgojIHNjQVRBQy1zZXEgZGF0YQoKCiMjIFFDIEFUQUMKCgpgYGB7cn0KcHJvaiA8LSBsb2FkQXJjaFJQcm9qZWN0KCIvb21pY3MvZ3JvdXBzL09FMDUzMy9pbnRlcm5hbC9rYXRoYXJpbmEvc2NEb1JJL2dhc3RydWxhdGlvbl9kYXRhX25ldy9LYXRoaS8wMV9vcmlnaW5hbF9zdWJzZXQvIikKCm1ldGFkYXRhIDwtIGdldENlbGxDb2xEYXRhKHByb2opICU+JSBhcy5kYXRhLmZyYW1lKCkKYGBgCgoKCmBgYHtyfQptZXRhZGF0YSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9kZW5zaXR5MmRfZmlsbGVkKGFlcyh4PWxvZzEwKG5GcmFnc19hdGFjICksIHk9VFNTRW5yaWNobWVudF9hdGFjKSwgYmlucz0yMCkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDUsIGNvbG9yPSJncmVlbiIsIGxpbmV0eXBlPSJkYXNoZWQiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMywgY29sb3I9ImdyZWVuIiwgbGluZXR5cGU9ImRhc2hlZCIpICsKICAjZ2VvbV94c2lkZWRlbnNpdHkoYWVzKHg9bG9nMTAocHJlX2ZpbHRlcl9tZXRhJG5GcmFncykpKSArCiAgI2dlb21feXNpZGVkZW5zaXR5KGFlcyh5ID0gcHJlX2ZpbHRlcl9tZXRhJFRTU0VucmljaG1lbnQpKSArCiAgZmFjZXRfd3JhcCh+c2FtcGxlKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgbGFicyh4ID0gIkxvZzEwIFVuaXF1ZSBGcmFnbWVudHMiLCB5ID0gIlRTUyBFbnJpY2htZW50IFNjb3JlIikKYGBgCgpUaGUgc2NBVEFDLXNlcSBzaG93cyB0aGF0IEU3LjUgc2VlbXMgdG8gYmUgb2YgbG93ZXIgcXVhbGl0eSwgd2hpY2ggd2UgaGF2ZSBhbHJlYWR5Cm9ic2VydmVkIGluIHRoZSBzY1JOQS1zZXEuIFBvdGVudGlhbGx5LCB0aGUgY2VsbHMgd2hlcmUgc2ltcGx5IGluIGEgd29yc2UgCmNvbmRpdGlvbiB3aGVuIHNlcXVlbmNlZC4KCmBgYHtyLCBmaWcud2lkdGg9MTB9CnAxIDwtIG1ldGFkYXRhICU+JSAKICBnZ3Bsb3QoKSArCiAgZ2dyaWRnZXM6Omdlb21fZGVuc2l0eV9yaWRnZXMoYWVzKHggPSBUU1NFbnJpY2htZW50X2F0YWMsIHkgPSBTYW1wbGUsIGZpbGwgPSBTYW1wbGUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gLjkpICsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJTZXQzIikgKwogIHRoZW1lKAogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwKICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIk5vbmUiLCAKICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JleSIpLCAgICMgTWFqb3IgZ3JpZCBsaW5lcwogICAgICAjc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiYmxhY2siLCBmaWxsID0gIndoaXRlIiksCiAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG91ciA9ICJibGFjayIpKQogIAoKcDIgPC0gbWV0YWRhdGEgJT4lIAogIGdncGxvdCgpICsKICBnZW9tX3Zpb2xpbihhZXMoeCA9IFNhbXBsZSwgeSA9IFRTU0VucmljaG1lbnQsIGZpbGwgPSBTYW1wbGUpLCBhbHBoYSA9IDAuOSkgKwogIGdlb21fYm94cGxvdChhZXMoeCA9IFNhbXBsZSwgeSA9IFRTU0VucmljaG1lbnQsZmlsbCA9IFNhbXBsZSksIGFscGhhID0gMC4yKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogIGxhYnModGl0bGUgPSAiVFNTIEVucmljaG1lbnQiKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iU2V0MyIpICsKICBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQodGl0bGU9InNhbXBsZSIpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUsIGhqdXN0PTEpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJOb25lIiwgCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JleSIpLCAgICMgTWFqb3IgZ3JpZCBsaW5lcwogICAgICAgICNzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJibGFjayIsIGZpbGwgPSAid2hpdGUiKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvdXIgPSAiYmxhY2siKSkKICAKCmNvd3Bsb3Q6OnBsb3RfZ3JpZChwMiwgcDEsIG5jb2wgPSAyKQoKYGBgCgo8ZGV0YWlscz4KPHN1bW1hcnk+UGxvdHMgZm9yIHJlcG9ydDwvc3VtbWFyeT4KCmBgYHtyLCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQ9NX0KCnAxIDwtIG1ldGFkYXRhICU+JSAKICBnZ3Bsb3QoKSArCiAgZ2VvbV92aW9saW4oYWVzKHggPSBTYW1wbGUsIHkgPSBUU1NFbnJpY2htZW50LCBmaWxsID0gU2FtcGxlKSwgYWxwaGEgPSAwLjkpICsKICBnZW9tX2JveHBsb3QoYWVzKHggPSBTYW1wbGUsIHkgPSBUU1NFbnJpY2htZW50LGZpbGwgPSBTYW1wbGUpLCBhbHBoYSA9IDAuMikgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsKICBsYWJzKHRpdGxlID0gIlRTUyBFbnJpY2htZW50IikgKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGU9IlNldDMiKSArCiAgZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPSJzYW1wbGUiKSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41LCBoanVzdD0xKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiTm9uZSIsIAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyZXkiKSwgICAjIE1ham9yIGdyaWQgbGluZXMKICAgICAgICAjc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiYmxhY2siLCBmaWxsID0gIndoaXRlIiksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImJsYWNrIikpCgpwMiA8LSBtZXRhZGF0YSAlPiUgCiAgZ2dwbG90KCkgKwogIGdlb21fdmlvbGluKGFlcyh4ID0gU2FtcGxlLCB5ID0gbkZyYWdzX2F0YWMgLCBmaWxsID0gU2FtcGxlKSwgYWxwaGEgPSAwLjYpICsKICBnZW9tX2JveHBsb3QoYWVzKHggPSBTYW1wbGUsIHkgPSBuRnJhZ3NfYXRhYyAsZmlsbCA9IFNhbXBsZSksIGFscGhhID0gMC4xKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogIGxhYnModGl0bGUgPSAiTnVtYmVyIG9mIHVuaXF1ZSBGcmFnbWVudHMiLCB5ID0gIiNGcmFnbWVudHMiKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iU2V0MyIpICsKICBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQodGl0bGU9InNhbXBsZSIpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUsIGhqdXN0PTEsIHNpemUgPSAxNSksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMjUpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJOb25lIiwgCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JleSIpLCAgICMgTWFqb3IgZ3JpZCBsaW5lcwogICAgICAgICNzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJibGFjayIsIGZpbGwgPSAid2hpdGUiKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvdXIgPSAiYmxhY2siKSkKCiAgCgpjb3dwbG90OjpwbG90X2dyaWQocDEsIHAyLCBuY29sID0gMikKCmdnc2F2ZShwYXN0ZTAocGxvdF9kaXIsICJxY19hdGFjLnBkZiIpKQoKYGBgCgoKCmBgYHtyfQptZXRhZGF0YSAlPiUgCiAgZ2dwbG90KCkgKwogIGdlb21fdmlvbGluKGFlcyh4ID0gU2FtcGxlLCB5ID0gbkZyYWdzX2F0YWMgLCBmaWxsID0gU2FtcGxlKSwgYWxwaGEgPSAwLjYpICsKICBnZW9tX2JveHBsb3QoYWVzKHggPSBTYW1wbGUsIHkgPSBuRnJhZ3NfYXRhYyAsZmlsbCA9IFNhbXBsZSksIGFscGhhID0gMC4xKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogIGxhYnModGl0bGUgPSAiTnVtYmVyIG9mIHVuaXF1ZSBGcmFnbWVudHMiLCB5ID0gIiNGcmFnbWVudHMiKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iU2V0MyIpICsKICBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQodGl0bGU9InNhbXBsZSIpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUsIGhqdXN0PTEpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJOb25lIiwgCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JleSIpLCAgICMgTWFqb3IgZ3JpZCBsaW5lcwogICAgICAgICNzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJibGFjayIsIGZpbGwgPSAid2hpdGUiKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvdXIgPSAiYmxhY2siKSkKCmBgYAoKCjwvZGV0YWlscz4KCmBgYHtyLCBmaWcud2lkdGg9MTB9CnAxIDwtIGF0YWNfc2V1cmF0QG1ldGEuZGF0YSAlPiUgCiAgZ2dwbG90KCkgKwogIGdncmlkZ2VzOjpnZW9tX2RlbnNpdHlfcmlkZ2VzKGFlcyh4ID0gbkZyYWdzX2F0YWMgLCB5ID0gU2FtcGxlLCBmaWxsID0gU2FtcGxlKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IC42KSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iU2V0MyIpICsKICB0aGVtZSgKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gIk5vbmUiLCAKICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyZXkiKSwgICAjIE1ham9yIGdyaWQgbGluZXMKICAgICNzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJibGFjayIsIGZpbGwgPSAid2hpdGUiKSwKICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG91ciA9ICJibGFjayIpKQoKcDIgPC0gYXRhY19zZXVyYXRAbWV0YS5kYXRhICU+JSAKICBnZ3Bsb3QoKSArCiAgZ2VvbV92aW9saW4oYWVzKHggPSBTYW1wbGUsIHkgPSBuRnJhZ3NfYXRhYyAsIGZpbGwgPSBTYW1wbGUpLCBhbHBoYSA9IDAuNikgKwogIGdlb21fYm94cGxvdChhZXMoeCA9IFNhbXBsZSwgeSA9IG5GcmFnc19hdGFjICxmaWxsID0gU2FtcGxlKSwgYWxwaGEgPSAwLjEpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgbGFicyh0aXRsZSA9ICJOdW1iZXIgb2YgdW5pcXVlIEZyYWdtZW50cyIpICsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJTZXQzIikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41LCBoanVzdD0xKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiTm9uZSIsIAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyZXkiKSwgICAjIE1ham9yIGdyaWQgbGluZXMKICAgICAgICAjc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiYmxhY2siLCBmaWxsID0gIndoaXRlIiksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImJsYWNrIikpCmNvd3Bsb3Q6OnBsb3RfZ3JpZChwMiwgcDEsIG5jb2wgPSAyKQpgYGAKCiMjIE5vcm1hbGl6YXRpb24gJiBEaW1lbnNpb25hbGl0eSByZWR1Y3Rpb24gQVRBQwoKKipMYXRlbnQgU2VtYW50aWMgSW5kZXhpbmcqKgoKMS4gVEYtSURGIG5vcm1hbGl6YXRpb24KICArIG5vcm1hbGl6ZSBhY3Jvc3MgY2VsbHMgKHNlcXVlbmNpbmcgZGVwdGgpCiAgKyBub3JtYWxpemUgYWNyb3NzIHBlYWsgKGhpZ2hlciB2YWx1ZXMgdG8gbW9yZSByYXJlIHBlYWtzKQoyLiBTZWxlY3QgVG9wIGZlYXR1cmVzCjMuICBSdW4gU1ZEIG9uIHNlbGVjdGVkIGZlYXR1cmVzCgpgYGAje3J9CmNvbFN1bXMoYXRhY19zZXVyYXRAYXNzYXlzJG9yaWdpbmFsZXhwQGRhdGEpCgphdGFjX3NldXJhdCA8LSBSdW5URklERihhdGFjX3NldXJhdCkKYXRhY19zZXVyYXQgPC0gRmluZFRvcEZlYXR1cmVzKGF0YWNfc2V1cmF0KQphdGFjX3NldXJhdCA8LSBSdW5TVkQoYXRhY19zZXVyYXQpCmBgYApUaGUgZmlyc3QgTFNJIGNvbXBvbmVudCBvZnRlbiBjYXB0dXJlcyBzZXF1ZW5jaW5nIGRlcHRoLiBXZSB3aWxsCnRoZXJlZm9yZSByZW1vdmUgaXQgZnJvbSBkb3duc3RyZWFtIGFuYWx5c2lzLiBUaGUgY29ycmVsYXRpb24gYmV0d2VlbiBzZXF1ZW5jaW5nCmRlcHRoIGFuZCBlYWNoIExTSSBjb21wb25lbnQgaXMgc2hvd24gaW4gdGhlIHBsb3QgYmVsb3cuCgpgYGAje3J9CkRlcHRoQ29yKGF0YWNfc2V1cmF0KQpgYGAKCiMjIFZpc3VhbGl6YXRpb24KCmBgYCN7cn0KYXRhY19zZXVyYXQgPC0gUnVuVU1BUChhdGFjX3NldXJhdCwgcmVkdWN0aW9uID0gImxzaSIsIGRpbXMgPSAyOjMwLCB2ZXJib3NlID0gRkFMU0UpCmFhdGFjX3NldXJhdCA8LSBGaW5kTmVpZ2hib3JzKGF0YWNfc2V1cmF0LCByZWR1Y3Rpb24gPSAibHNpIiwgZGltcyA9IDI6MzAsIHZlcmJvc2UgPSBGQUxTRSkKCiMgZm9yIENsc3V0ZXJpbmcgaW5zdGVhZCBvZiBMb3V2aWFuIFNMTSBhbGdvcml0aG0gaXMgdXNlZAojYXRhY19zZXVyYXQgPC0gRmluZENsdXN0ZXJzKGF0YWNfc2V1cmF0LCB2ZXJib3NlID0gRkFMU0UsIGFsZ29yaXRobSA9IDMpIApgYGAKCgoKYGBgI3tyLCBmaWcud2lkdGggPSAxNSwgZmlnLmhlaWdodD0xMH0KCkRpbVBsb3QoYXRhY19zZXVyYXQsIGdyb3VwLmJ5ID0gImNlbGx0eXBlLm1hcHBlZF9zZXVyYXQiLCByZWR1Y3Rpb24gPSAidW1hcCIsIHB0LnNpemUgPSAxLCBjb2xzID0gY29sKSArCiAgbGFicyh0aXRsZSA9ICJzY0FUQUMtc2VxIENlbGx0eXBlIikKICAKRGltUGxvdChhdGFjX3NldXJhdCwgZ3JvdXAuYnkgPSAic2FtcGxlIiwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgY29scyA9IGNvbCkgKwogIGxhYnModGl0bGUgPSAic2NBVEFDLXNlcSBDZWxsdHlwZSIpCmBgYAoKYGBgI3tyLCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQ9MTB9CkRpbVBsb3Qocm5hX3NldXJhdCAsIGdyb3VwLmJ5ID0gImNlbGx0eXBlLm1hcHBlZF9zZXVyYXQiLCBwdC5zaXplID0gMSwgY29scyA9IGNvbCwKICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIpICsKICBsYWJzKHRpdGxlID0gInNjUk5BLXNlcSBDZWxsdHlwZSIpCgpgYGAKCgpMZXRzIGhhdmUgYSBsb29rIGF0IHdoZXRoZXIgdGhlIG51bWJlciBvZiBmcmFnbWVudHMgaXMgY29ycmVsYXRlZCB0byB0aGUgCm51bWJlciBvZiBjb3VudHMgaW4gZWFjaCBjZWxsdHlwZS4gVGhpcyBzZWVtcyB0byBiZSB0aGUgY2FzZS4KCgpgYGAje3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD04fQphdGFjX3NldXJhdEBtZXRhLmRhdGEgJT4lIAogIGdncGxvdChhZXMoeCA9IGxvZzEwKG5Db3VudF9vcmlnaW5hbGV4cCApLCB5ID0gbG9nMTAobkZyYWdzX2F0YWMpKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAuMiwgc2l6ZSA9IC4yKSArCiAgZ2dzaWRlOjpnZW9tX3hzaWRlZGVuc2l0eSgpICsKICBnZ3NpZGU6Omdlb21feXNpZGVkZW5zaXR5KCkgKwogIGZhY2V0X3dyYXAofnNhbXBsZSkgKwogIGxhYnMoeCA9ICJMb2cxMCBDb3VudHMiLCB5ID0gImxvZzEwIFVuaXF1ZSBGcmFnbWVudHMiKQpgYGAKCgpgYGAje3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD0xMH0KYXRhY19zZXVyYXRAbWV0YS5kYXRhICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBsb2cxMChuQ291bnRfb3JpZ2luYWxleHApLCB5ID0gbG9nMTAoVFNTRW5yaWNobWVudCkpKSArCiAgZ2VvbV9wb2ludChzaXplID0gLjIsIGFscGhhID0gLjIpICsKICBnZ3NpZGU6Omdlb21feHNpZGVkZW5zaXR5KCkgKwogIGdnc2lkZTo6Z2VvbV95c2lkZWRlbnNpdHkoKSArCiAgZmFjZXRfd3JhcCh+c2FtcGxlKQpgYGAKCgpgYGAje3J9CmF0YWNfc2V1cmF0QG1ldGEuZGF0YSAlPiUgCiAgZ2dwbG90KCkgKwogIGdlb21faGlzdG9ncmFtKGFlcyh4ID0gUHJvbW90ZXJSYXRpb19hdGFjKSkgCgphdGFjX3NldXJhdEBtZXRhLmRhdGEgJT4lIAogIGdncGxvdCgpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMoeCA9IE51Y2xlb3NvbWVSYXRpb19hdGFjKSkgCmBgYAoKCgpgYGB7cn0KI3NhdmVSRFMoYXRhY19zZXVyYXQsICJhdGFjX1NldXJhdF9vYmplY3QiKQojc2F2ZVJEUyhybmFfc2V1cmF0LCAicm5hX1NldXJhdF9vYmplY3QiKQpgYGAKCgo=